The documentation for Future.catchError
could be a lot clearer, but the relevant part is:
onError
is called with the error and possibly stack trace, and the returned future is completed with the result of this call in exactly the same way as forthen
‘sonError
.
Cross-referencing to the documentation for Future.then
, the relevant portion is:
The
onError
callback must return a value or future that can be used to complete the returned future, so it must be something assignable toFutureOr<R>
.
Since File.readAsString
returns a Future<String>
, your catchError
callback also must return a Future<String>
. Examples of doing that:
File("foo.txt").readAsString().catchError((e) {
print(e);
return Future.value('');
});
File("foo.txt").readAsString().catchError((e) async {
print(e);
return '';
});
Logically, this makes sense; because given:
String value = await File("foo.txt").readAsString().catchError(...);
then if readAsString
succeeds, value
should be assigned a String
. If it fails, since you catch the exception without rethrowing it, value
still needs to be assigned a String
.
Put another way, your code is equivalent to:
Future<String> readFoo() async {
try {
return await File("foo.txt").readAsString();
} catch (e) {
print(e);
}
// Oops, missing return value.
}
In general, I strongly recommend using async
/await
with try
–catch
instead of using .catchError
, which would avoid this confusion.