is there any way to cancel a dart Future?
You can use CancelableOperation or CancelableCompleter to cancel a future. See below the 2 versions:
Solution 1: CancelableOperation
(included in a test so you can try it yourself):
cancel a future
test("CancelableOperation with future", () async { var cancellableOperation = CancelableOperation.fromFuture( Future.value('future result'), onCancel: () => {debugPrint('onCancel')}, );// cancellableOperation.cancel(); // uncomment this to test cancellation cancellableOperation.value.then((value) => { debugPrint('then: $value'), }); cancellableOperation.value.whenComplete(() => { debugPrint('onDone'), });});
cancel a stream
test("CancelableOperation with stream", () async { var cancellableOperation = CancelableOperation.fromFuture( Future.value('future result'), onCancel: () => {debugPrint('onCancel')}, ); // cancellableOperation.cancel(); // uncomment this to test cancellation cancellableOperation.asStream().listen( (value) => { debugPrint('value: $value') }, onDone: () => { debugPrint('onDone') }, );});
Both above tests will output:
then: future resultonDone
Now if we uncomment the cancellableOperation.cancel();
then both above tests will output:
onCancel
Solution 2: CancelableCompleter
(if you need more control)
test("CancelableCompleter is cancelled", () async { CancelableCompleter completer = CancelableCompleter(onCancel: () { print('onCancel'); }); // completer.operation.cancel(); // uncomment this to test cancellation completer.complete(Future.value('future result')); print('isCanceled: ${completer.isCanceled}'); print('isCompleted: ${completer.isCompleted}'); completer.operation.value.then((value) => { print('then: $value'), }); completer.operation.value.whenComplete(() => { print('onDone'), });});
Output:
isCanceled: falseisCompleted: truethen: future resultonDone
Now if we uncomment the cancellableOperation.cancel();
we get output:
onCancelisCanceled: trueisCompleted: true
Be aware that if you use await cancellableOperation.value
or await completer.operation
then the future will never return a result and it will await indefinitely if the operation was cancelled. This is because await cancellableOperation.value
is the same as writing cancellableOperation.value.then(...)
but then()
will never be called if the operation was cancelled.
Remember to add async Dart package.
How to cancel Future.delayed
A simple way is to use Timer
instead :)
Timer _timer;void _schedule() { _timer = Timer(Duration(seconds: 2), () { print('Do something after delay'); });}@overridevoid dispose() { super.dispose(); _timer?.cancel();}
As far as I know, there isn't a way to cancel a Future. But there is a way to cancel a Stream subscription, and maybe that can help you.
Calling onSubmit
on a button returns a StreamSubscription
object. You can explicitly store that object and then call cancel()
on it to cancel the stream subscription:
StreamSubscription subscription = someDOMElement.onSubmit.listen((data) { // you code here if (someCondition == true) { subscription.cancel(); }});
Later, as a response to some user action, perhaps, you can cancel the subscription: