50

I'm exploring Futures in Dart, and I'm confused about these two methods that Future offers, .then() and .whenCompleted(). What's the main difference between them?

Lets say I want to read a .txt using .readAsString(), I would do it like this:

void main(){
  File file = new File('text.txt');
  Future content = file.readAsString();
  content.then((data) {
    print(content);
  });  
}

So .then() is like a callback that fires a function once the Future is completed.

But I see there is also .whenComplete() that can also fire a function once Future completes. Something like this :

void main(){
  File file = new File('text.txt');
  Future content = file.readAsString();
  content.whenComplete(() {
    print("Completed");
  });
}

The difference I see here is that .then() has access to data that was returned! What is .whenCompleted() used for? When should we choose one over the other?

Matija
  • 2,610
  • 1
  • 18
  • 18

3 Answers3

71

.whenComplete will fire a function either when the Future completes with an error or not, instead .then will fire a function after the Future completes without an error.

Quote from the .whenComplete API DOC

This is the asynchronous equivalent of a "finally" block.

Mattia
  • 5,909
  • 3
  • 26
  • 41
  • 1
    They are not actual types, but [generics](https://www.dartlang.org/guides/language/language-tour#generics). – Mattia Mar 27 '19 at 18:05
  • 2
    Not actually... if you put `then` after `catchError` , `then` is called because `catchError` returns a completely new Future, indeed if were to return an error inside `catchError` `.then` won't be fired, in asynchronous code your code would be something like this: https://gist.github.com/Hexer10/87a6f38616f74321c85f2f91a5450d4e – Mattia May 11 '20 at 18:09
18

then runs if the future completes successfully.

catchError runs if the future fails.

whenComplete runs regardless of the future completed with a value or with an error.

Here's the basic flow:

someFuture().then((value) {
  print('Future finished successfully i.e. without error');
}).catchError((error) {
  print('Future finished with error');
}).whenComplete(() {
  print('Either of then or catchError has run at this point');
});
iDecode
  • 22,623
  • 19
  • 99
  • 186
  • 1
    You're registering a `Future.then` callback on the `Future` returned by `catchError`, not on the original `Future`. That is, you're explicitly setting your `.then` callback to wait for `.catchError` to complete. – jamesdlin May 20 '22 at 16:50
  • @jamesdlin Sorry, I was new to `Future` back then and thanks, I've updated the code. – iDecode May 20 '22 at 18:50
3

.whenComplete = The function inside .whenComplete is called when this future completes, whether it does so with a value or with an error.

.then = Returns a new Future which is completed with the result of the call to onValue (if this future completes with a value) or to onError (if this future completes with an error)

Read detail on API DOC

whenComplete then

Abdulhakim Zeinu
  • 3,333
  • 1
  • 30
  • 37