未来的 catchError 函数在未立即链接时不会捕获错误
Future catchError function doesn't catch error when its not chained immediately
考虑这段代码:
示例 A:
Future<void> fakeCall() async {
await Future.delayed(const Duration(milliseconds: 300), () {
throw MyError('myException');
});
}
Future<void> fetch() async {
Future<void> testFuture = fakeCall();
testFuture.whenComplete(() {
print('when completed');
});
testFuture.catchError((e) {
print('on error');
});
return testFuture;
}
void main() async {
try{
await fetch();
}on MyError catch(e){
//getting here but one still leaks!!
}
}
当调用 await fetch()
时,我希望只调用 catchError
。但是错误以某种方式泄漏,所以基本上有两个被抛出...一个被 catchError
捕获,另一个作为未处理的错误泄漏到外面。
但使用建议的方式(一个接一个地链接):
示例 B:
Future<void> fakeCall() async {
await Future.delayed(const Duration(milliseconds: 300), () {
throw MyError('myException');
});
}
Future<void> fetch() async {
Future<void> testFuture = fakeCall().whenComplete(() {
print('when completed');
}).catchError((e) {
print('on error');
});
return testFuture;
}
void main() async {
try{
await fetch();
}on MyError catch(e){
//getting here and nothing leaks!!
}
}
没有发生错误泄漏。
这让我很好奇,
谁能解释一下为什么第一种写法会导致错误泄露?
更新
原来我忘了在fetch函数周围加上try/catch,所以
您可能认为错误是由于这个原因而泄露的。但请注意,当没有正确链接 onError 时,错误仍然会泄漏(第一个示例)
错误已泄露,因为您正在等待 Future
的结果,最终完成时出现以下错误:
await fetch();
重要的是要了解 Future
对象只是一个值,它有时会在将来获得一个值,这个值可以是一个值也可以是一个错误。
catchError()
是一种订阅一些代码的方法,如果 Future
作为错误完成,则要执行的代码。方法 returns 一个新的未来,其逻辑是它在原始未来完成的情况下获得原始值而没有任何错误。但是,如果 origin 完成时出现错误,catchError()
将运行指定的方法并 returns 执行后的值。
catchError()
不会改变原点 Future
的任何内容,因此您可以根据需要多次调用 catchError()
。
我应该补充一点,我认为在异步标记的函数中使用传统的 try...catch(结合 await
)比使用 catchError()
更好,因为它使得代码更易读,更不易混淆:
Future<void> fetch() async {
try {
await fakeCall();
} catch (e) {
print('on error');
} finally {
print('when completed');
}
}
void main() async {
await fetch();
}
输出:
on error
when completed
问题更改后更新
“示例 B”的问题在于您假设 whenComplete()
确实处理了任何错误。但是如果你阅读文档:
The future returned by this call, f
, will complete the same way as this future unless an error occurs in the action
call, or in a Future returned by the action
call. If the call to action
does not return a future, its return value is ignored.
https://api.dart.dev/stable/2.15.1/dart-async/Future/whenComplete.html
所以返回的 Future
没有改变它的行为,所以如果原点 Future
完成时出现错误,从 whenComplete()
创建的 Future
也会发生同样的情况.由于您没有在此 Future
上附加任何错误处理,您的程序失败了。
考虑这段代码:
示例 A:
Future<void> fakeCall() async {
await Future.delayed(const Duration(milliseconds: 300), () {
throw MyError('myException');
});
}
Future<void> fetch() async {
Future<void> testFuture = fakeCall();
testFuture.whenComplete(() {
print('when completed');
});
testFuture.catchError((e) {
print('on error');
});
return testFuture;
}
void main() async {
try{
await fetch();
}on MyError catch(e){
//getting here but one still leaks!!
}
}
当调用 await fetch()
时,我希望只调用 catchError
。但是错误以某种方式泄漏,所以基本上有两个被抛出...一个被 catchError
捕获,另一个作为未处理的错误泄漏到外面。
但使用建议的方式(一个接一个地链接):
示例 B:
Future<void> fakeCall() async {
await Future.delayed(const Duration(milliseconds: 300), () {
throw MyError('myException');
});
}
Future<void> fetch() async {
Future<void> testFuture = fakeCall().whenComplete(() {
print('when completed');
}).catchError((e) {
print('on error');
});
return testFuture;
}
void main() async {
try{
await fetch();
}on MyError catch(e){
//getting here and nothing leaks!!
}
}
没有发生错误泄漏。 这让我很好奇, 谁能解释一下为什么第一种写法会导致错误泄露?
更新
原来我忘了在fetch函数周围加上try/catch,所以 您可能认为错误是由于这个原因而泄露的。但请注意,当没有正确链接 onError 时,错误仍然会泄漏(第一个示例)
错误已泄露,因为您正在等待 Future
的结果,最终完成时出现以下错误:
await fetch();
重要的是要了解 Future
对象只是一个值,它有时会在将来获得一个值,这个值可以是一个值也可以是一个错误。
catchError()
是一种订阅一些代码的方法,如果 Future
作为错误完成,则要执行的代码。方法 returns 一个新的未来,其逻辑是它在原始未来完成的情况下获得原始值而没有任何错误。但是,如果 origin 完成时出现错误,catchError()
将运行指定的方法并 returns 执行后的值。
catchError()
不会改变原点 Future
的任何内容,因此您可以根据需要多次调用 catchError()
。
我应该补充一点,我认为在异步标记的函数中使用传统的 try...catch(结合 await
)比使用 catchError()
更好,因为它使得代码更易读,更不易混淆:
Future<void> fetch() async {
try {
await fakeCall();
} catch (e) {
print('on error');
} finally {
print('when completed');
}
}
void main() async {
await fetch();
}
输出:
on error
when completed
问题更改后更新
“示例 B”的问题在于您假设 whenComplete()
确实处理了任何错误。但是如果你阅读文档:
The future returned by this call,
f
, will complete the same way as this future unless an error occurs in theaction
call, or in a Future returned by theaction
call. If the call toaction
does not return a future, its return value is ignored.
https://api.dart.dev/stable/2.15.1/dart-async/Future/whenComplete.html
所以返回的 Future
没有改变它的行为,所以如果原点 Future
完成时出现错误,从 whenComplete()
创建的 Future
也会发生同样的情况.由于您没有在此 Future
上附加任何错误处理,您的程序失败了。