async_queue
이 dart 패키지는 비동기 작업 그룹이 순서대로 하나씩 실행되도록 보장합니다.
samderlust/async_queue open-source repository details.
아래는 영문 원문 스냅샷입니다. 최신 내용은 GitHub에서 확인하세요.
This dart package ensures your pack of async tasks executes in order, one after the other.
addJob returns a Future — await individual job results directly, no more listener workaroundsretryTime without manual retry() callsonError callback — handle errors at the queue level: AsyncQueue(onError: (error, label) { ... })addJob(..., priority: 10) to run important jobs firstpause() halts without losing jobs, resume() continuesaddJob(..., retryDelay: Duration(seconds: 2)) to wait between retriesaddJob(..., timeout: Duration(seconds: 30)) to auto-fail slow jobsisRunning, isPaused, isClosedaddJob returns a Future — await individual job resultsonError callback for dedicated error handlingisRunning / isPaused / isClosed state gettersLike any other package, add the library to your pubspec.yaml dependencies:
dependencies:
async_queue: <latest_version>
Then import it wherever you want to use it:
import 'package:async_queue/async_queue.dart';
final asyncQ = AsyncQueue();
asyncQ.addJob((_) =>
Future.delayed(const Duration(seconds: 1), () => print("normalQ: 1")));
asyncQ.addJob((_) =>
Future.delayed(const Duration(seconds: 4), () => print("normalQ: 2")));
asyncQ.addJob((_) =>
Future.delayed(const Duration(seconds: 2), () => print("normalQ: 3")));
asyncQ.addJob((_) =>
Future.delayed(const Duration(seconds: 1), () => print("normalQ: 4")));
await asyncQ.start();
// normalQ: 1
// normalQ: 2
// normalQ: 3
// normalQ: 4
final autoAsyncQ = AsyncQueue.autoStart();
autoAsyncQ.addJob((_) =>
Future.delayed(const Duration(seconds: 1), () => print("AutoQ: 1")));
await Future.delayed(const Duration(seconds: 6));
autoAsyncQ.addJob((_) =>
Future.delayed(const Duration(seconds: 0), () => print("AutoQ: 1.2")));
autoAsyncQ.addJob((_) =>
Future.delayed(const Duration(seconds: 0), () => print("AutoQ: 1.3")));
autoAsyncQ.addJob((_) =>
Future.delayed(const Duration(seconds: 4), () => print("AutoQ: 2")));
autoAsyncQ.addJob((_) =>
Future.delayed(const Duration(seconds: 3), () => print("AutoQ: 2.2")));
autoAsyncQ.addJob((_) =>
Future.delayed(const Duration(seconds: 2), () => print("AutoQ: 3")));
autoAsyncQ.addJob((_) =>
Future.delayed(const Duration(seconds: 1), () => print("AutoQ: 4")));
// AutoQ: 1
// AutoQ: 1.2
// AutoQ: 1.3
// AutoQ: 2
// AutoQ: 2.2
// AutoQ: 3
// AutoQ: 4
final asyncQ = AsyncQueue();
asyncQ.addQueueListener((event) => print("$event"));
addJob returns a Future that completes with the job's return value. This works alongside previousResult — they serve different purposes.
final q = AsyncQueue.autoStart();
// Each addJob returns a Future you can await for its result
final userFuture = q.addJob((_) async {
return await api.getUser(); // returns "Sam"
});
// previousResult still chains between jobs
final postsFuture = q.addJob((previousResult) async {
return await api.getPostsFor(previousResult);
});
final user = await userFuture; // "Sam"
final posts = await postsFuture; // [Post, Post, ...]
Jobs that throw are automatically retried up to retryTime times. You no longer need to catch errors and call retry() manually (though you still can for custom logic).
q.addJob((_) async {
// if this throws, it will be retried automatically
return await api.fetchData();
}, retryTime: 3);
Handle errors at the queue level without parsing events:
final q = AsyncQueue(
onError: (error, jobLabel) {
print('Job $jobLabel failed: $error');
},
);
Higher priority jobs execute before lower priority ones. Default is 0. Same-priority jobs maintain FIFO order.
q.addJob((_) => lowPriorityTask(), priority: 1);
q.addJob((_) => highPriorityTask(), priority: 10); // runs first
Unlike stop() which destroys the queue, pause() preserves all queued jobs:
q.pause(); // current job finishes, no new jobs start
q.resume(); // picks up where it left off
Add a delay between retry attempts:
q.addJob((_) => callApi(), retryTime: 3, retryDelay: Duration(seconds: 2));
Auto-fail a job if it exceeds a duration. Timed-out jobs trigger auto-retry like any other exception:
q.addJob((_) => slowTask(), timeout: Duration(seconds: 30));
q.addJob(() async {
try {
//do something
} catch (e) {
q.retry();
}
},
//default is 1
retryTime: 3,
);
This package would be useful if you have multiple widgets in a screen or even in multiple screens that need to do some async requests that are related to each other.
For examples:
Code example:
@override
Widget build(BuildContext context) {
final aQ = AsyncQueue.autoStart();
return Scaffold(
body: Column(
children: [
TextButton(
onPressed: () async {aQ.addJob((_) => Future.delayed(const Duration(seconds: 2), () => print("job1 ")));},
child: const Text('job1'),
),
TextButton(
onPressed: () async {aQ.addJob((_) => Future.delayed(const Duration(seconds: 4), () => print("jobs2")));},
child: const Text('job2'),
),
TextButton(
onPressed: () async {aQ.addJob((_) => Future.delayed(const Duration(seconds: 1), () => print("job3")));},
child: const Text('job3'),
),
],
),
);
}
If you find anything need to be improve or want to request a feature. Please go ahead and create an issue in the Github repo