Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

is there any way to cancel a dart Future?

In a Dart UI, I have a button [submit] to launch a long async request. The [submit] handler returns a Future. Next, the button [submit] is replaced by a button [cancel] to allow the cancellation of the whole operation. In the [cancel] handler, I would like to cancel the long operation. How can I cancel the Future returned by the submit handler? I found no method to do that.

like image 234
Serge Tahé Avatar asked Jul 09 '13 15:07

Serge Tahé


People also ask

How do I cancel Future darts?

Many of you know that you can't cancel a Future in Dart, but you can cancel a subscription to a Stream. So one way you could handle this situation is to rewrite getData() to return a Stream instead.

How do you wait for Future to complete Dart?

To prevent multiple awaits, chaining futures in . then(), you can simply use Future. wait([]) that returns an array of results you were waiting for. If any of those Futures within that array fails, Future.

What is a Future in Dart?

A future (lower case “f”) is an instance of the Future (capitalized “F”) class. A future represents the result of an asynchronous operation, and can have two states: uncompleted or completed. Note: Uncompleted is a Dart term referring to the state of a future before it has produced a value.


2 Answers

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 result onDone 

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: false isCompleted: true then: future result onDone 

Now if we uncomment the cancellableOperation.cancel(); we get output:

onCancel isCanceled: true isCompleted: 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.

Code gist

like image 83
vovahost Avatar answered Sep 17 '22 07:09

vovahost


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');   }); }  @override void dispose() {   super.dispose();   _timer?.cancel(); } 
like image 43
Andrey Gordeev Avatar answered Sep 17 '22 07:09

Andrey Gordeev