I'm learning dart. I can't figure it out why the following dart code can't handle an exception. What wrong am I doing below?:
void main() {
print(1);
try {
File file = File('random_path.txt');
print(2);
var contents = file.readAsString();
print(3);
contents.then((value) => print(value));
print(4);
} on FileSystemException catch (e) {
print(5);
print(e);
} catch (e) {
print(6);
print(e);
} finally {
print(7);
}
print(8);
}
The file random_path.txt
doesn't exist. I was expecting the on FileSystemException catch(e)
to catch and print e
. But that's not a case. Here is the output:
1
2
3
4
7
8
Unhandled exception:
FileSystemException: Cannot open file, path = 'random_path.txt' (OS Error: No such file or directory, errno = 2)
#0 _File.open.<anonymous closure> (dart:io/file_impl.dart:356:9)
<asynchronous suspension>
CodePudding user response:
You need to handle the error that is reported by the contents
future, and forwarded to the future returned by then
.
That means either adding an error handler yourself:
contents.then(print).catchError((e, s) {
print("Future error: $e\n$s");
}); // Catches errors from `contents` or thrown by `print`.
// or
contents.then(print, one rror: (e, s) {
print("Future error: $e\n$s");
}); // Won't catch error thrown by `print`.
Or using an async
function to handle the future using await
,
which is the recommended approach:
void main() async { // <- marked as async so you can use `await`.
print(1);
try {
File file = File('random_path.txt');
print(2);
Future<String> contents = file.readAsString();
print(3);
var value = await contents; // <- await gets value, or rethrows error
print(value);
print(4);
} on FileSystemException catch (e) {
print(5);
print(e);
} catch (e) {
print(6);
print(e);
} finally {
print(7);
}
print(8);
}
In general, always use async
functions and await
to deal with futures.
Using the .then
API is mainly for low-level code which integrates different
asynchronous computations, and has to wait for more than one thing at a time.
It's what's being used internally to build a good Future
based API that you can just await
on. And you should just await
when you can.