Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Dart, if I use Future.wait with a list of Futures and an error is thrown on one of the Futures, what happens to the other Futures?

Tags:

dart

If I have the following code:

Future<int> a = new Future(() { print('a'); return 1; });
Future<int> b = new Future.error('Error!');
Future<int> c = new Future(() { print('c'); return 3; });

Future.wait([a, b, c])
  .then((List<int> values) => print(values))
  .catchError((e) => print(e));

What is printed?

Does the error caught by catchError have any idea of what Future died? Or which Futures remain?

like image 798
Juniper Belmont Avatar asked Apr 15 '13 18:04

Juniper Belmont


People also ask

How do you wait for Future to complete Dart?

Sometimes you need to have results of multiple async functions before starting to work on something else. To prevent multiple awaits, chaining futures in . then(), you can simply use Future. wait([]) that returns an array of results you were waiting for.

How do you handle Future errors?

Error handling within then() For more granular error handling, you can register a second ( onError ) callback within then() to handle Futures completed with errors. Here is then() 's signature: Future<R> then<R>(FutureOr<R> Function(T value) onValue, {Function? onError});


2 Answers

Determining what is printed is pretty easy by running it (do you not have a Dart VM handy?):

a
c
AsyncError: 'Error!'

The documentation for Future.wait() says:

Wait for all the given futures to complete and collect their values.

Returns a future which will complete once all the futures in a list are complete. If any of the futures in the list completes with an error, the resulting future also completes with an error. Otherwise the value of the returned future will be a list of all the values that were produced.

e.error is the value that was created with ('Error!', in this case), so by setting that to something indicating which Future has the error, you can see which Future "died". Of course, if you're not the one creating the error, that doesn't help.

In general, I think you use Future.wait() on a List like this when an error in any of them would be handled similarly. Needing to know which one failed might be a sign that you don't want to wait() on all of them together.

Update: I just realized the question title asks a question not asked in the question body: What happens to the other Futures?

The other Futures keep running. The Future returned by wait() throws whichever error it receives as soon as it receives it, so all return values are lost, and if any of the other Futures throws an error, it isn't caught, but each Future still runs until returning or throwing an error.

like image 154
Darshan Rivka Whittle Avatar answered Sep 28 '22 07:09

Darshan Rivka Whittle


AFAIK, you won't know precisely which Future generated the error. But, you can query the error object and get some useful information:

Future.wait([a, b, c])
.then((List<int> values) => print(values))
.catchError((e) {
  print(e.error);
  print(e.stackTrace);
  print(e.runtimeType);
  print(e.error.runtimeType);
});

Running this prints:

a
c
Error!
null
AsyncError
String

This tells us that the original error was a String. I don't know how useful that is to you, but its something.

like image 21
Shailen Tuli Avatar answered Sep 28 '22 07:09

Shailen Tuli