Consider the following code
import 'dart:async'; Future main() async { try { print("trying"); await doSomething(); print("success"); } catch (e) { print("caught"); } } Future<int> doSomething() async { await doSomethingElse(); return 5; } Future<int> doSomethingElse() async { throw new Exception(); }
When launched, the exception thrown in doSomethingElse() gets into main() , and everything works as expected. But, say, the person who wrote the doSomething() method did not understand that doSomethingElse() was asynchronous and instead wrote the following (note the missing await ).
Future<int> doSomething() async { doSomethingElse(); return 5; }
Now the exception is not caught at all. Rather, the output now looks like this:
trying success Unhandled exception: Uncaught Error: Exception Stack Trace: #0 doSomethingElse.<doSomethingElse_async_body> (file:///C:/code/test.dart:19:7) #1 Future.Future.<anonymous closure> (dart:async/future.dart:118) <snip>
What happens is that doSomething() returns immediately, and then later, in a different context, doSomethingElse() throws its error, stopping all execution immediately. I know that the answer to this may be "Well, then do not do this." but I am considering cases where I can not control the methods that I call (say, if they are part of the library).
This situation leads to two related issues:
- As the author of
main() , can I be sure that my call to doSomething() will not end with an unhandled exception? Or am I dependent on the author of doSomething() to make sure that all possible exceptions are handled or propagated to the returned Future? Is there a way to bind some kind of global error handler that can catch errors from abandoned futures? - As the author of
doSomething() , if I do not want to wait on doSomethingElse() (let's say it writes to the log, for example, I do not need output, and I do not need to worry about processing errors). Is there anything I can do to prevent doSomethingElse() from stopping a program other than wrapping every call to this try / catch block (which can be cumbersome, easily overlooked)? - As the author of
doSomethingElse() , is there some kind of pattern that I can use that allows me to exclude Exceptions so that callers who are waiting for the Future to complete can handle this Exception on their own, while callers who are not waiting for the Future do not need to worry about catching an exception? My best thought in this regard is to return a special object and not throw an exception, but this adds a lot of extra steepness and makes the method more complicated.
Note. I use async / await syntax here, but the question should be equally relevant for a more strictly future build (where do you return the new Future in doSomething() instead of .then() doSomethingElse()
source share