Author: Petrus Nguyễn Thái Học
Dart Cancellation Token. Inspired by CancellationToken in C#. A Dart utility package for easy async task cancellation.
- Reuse a single
CancellationToken
for multiple tasks, and cancel all of them with a single call toCancellationToken.cancel()
. - Cancel futures and clean-up resources with
token.guardFuture(block)
. - Cancel streams and clean-up resources with
token.guardStream(stream)
/Stream.guardedBy(token)
. - Integrate with rxdart/rxdart_ext with
useCancellationToken
. - Very simple, lightweight, performant, and easy to use.
dependencies:
cancellation_token_hoc081098: <latest_version>
import 'package:cancellation_token_hoc081098/cancellation_token_hoc081098.dart';
void main() async {
// Create a CancellationToken
final token = CancellationToken();
// Simulate a long-running task
Future<void> doWork(int number) async {
print('doWork($number) started');
await Future<void>.delayed(const Duration(milliseconds: 100));
print('doWork($number) finished');
}
// Guard a Future
final future = token.guardFuture(() async {
for (var i = 0; i < 10; i++) {
token.guard(); // Throws if token is cancelled
await doWork(i);
token.guard(); // Throws if token is cancelled
}
return 42;
});
future
.then((v) => print('Result: $v'))
.onError<Object>((e, st) => print('Error: $e'));
// Cancel the token after 300ms
await Future<void>.delayed(const Duration(milliseconds: 300));
// Cancel the token
token.cancel();
// Wait a little longer to ensure that the Future is cancelled
await Future<void>.delayed(const Duration(seconds: 2));
// Output:
// doWork(0) started
// doWork(0) finished
// doWork(1) started
// doWork(1) finished
// doWork(2) started
// Error: CancellationException
// doWork(2) finished
}
void main() async {
// Create a CancellationToken
final token = CancellationToken();
// Simulate a long-running task
Future<void> doWork(int number) async {
print('doWork($number) started');
await Future<void>.delayed(const Duration(milliseconds: 100));
print('doWork($number) finished');
}
// Guard a Stream
final stream = Rx.fromCallable(() async {
for (var i = 0; i < 10; i++) {
token.guard(); // Throws if token is cancelled
await doWork(i);
token.guard(); // Throws if token is cancelled
}
return 42;
}).guardedBy(token);
stream
.doOnData((v) => print('Result: $v'))
.doOnError((e, st) => print('Error: $e'))
.listen(null);
// Cancel the token after 300ms
await Future<void>.delayed(const Duration(milliseconds: 300));
// Cancel the token
token.cancel();
// Wait a little longer to ensure that the stream is cancelled
await Future<void>.delayed(const Duration(seconds: 2));
// Output:
// doWork(0) started
// doWork(0) finished
// doWork(1) started
// doWork(1) finished
// doWork(2) started
// Error: CancellationException
// doWork(2) finished
}
import 'package:rxdart_ext/rxdart_ext.dart';
void main() async {
// Simulate a long-running task
Future<void> doWork(int number) async {
print('doWork($number) started');
await Future<void>.delayed(const Duration(milliseconds: 100));
print('doWork($number) finished');
}
// useCancellationToken
final Single<int> single = useCancellationToken((cancelToken) async {
for (var i = 0; i < 10; i++) {
cancelToken.guard(); // Throws if token is cancelled
await doWork(i);
cancelToken.guard(); // Throws if token is cancelled
}
return 42;
});
final subscription = single
.doOnData((v) => print('Result: $v'))
.doOnError((e, st) => print('Error: $e'))
.listen(null);
// Cancel the subscription after 300ms
await Future<void>.delayed(const Duration(milliseconds: 300));
// Cancel the subscription
await subscription.cancel();
// Wait a little longer to ensure that the stream is cancelled
await Future<void>.delayed(const Duration(seconds: 2));
// Output:
// doWork(0) started
// doWork(0) finished
// doWork(1) started
// doWork(1) finished
// doWork(2) started
// doWork(2) finished
}
Please file feature requests and bugs at the issue tracker.
MIT License
Copyright (c) 2022 Petrus Nguyễn Thái Học