我想了解何时在异步函数中使用throw
和return Future.error
。选择一个或另一个时,我们应该考虑任何潜在的差异吗?
我做了一个小测试:
Future testFuture() async {
return Future.error('error from future');
}
void testThrow() {
throw('error from throw');
}
Future testFutureThrow() async {
throw('error from future throw');
}
main() async {
print('will run test');
try{
await testFuture();
}
catch(e){
print(e);
}
try{
testThrow();
}
catch(e){
print(e);
}
try{
await testFutureThrow();
}
catch(e){
print(e);
}
testFuture().catchError((e) => print(e));
testFutureThrow().catchError((e) => print(e));
print('did run test');
}
它们似乎都以相同的方式工作。这是输出:
will run test
error from future
error from throw
error from future throw
did run test
error from future
error from future throw
从此测试中我们可以看到,从调用者的角度来看,当使用try/catch
调用函数时,代码是同步运行的;如果我们Future.catchError
是异步的,则代码将同步运行。但是从功能流程的角度来看,它似乎是相同的。
注意:我起初是为了回答问题。但是后来我意识到我不是在回答而是在提问。
答案 0 :(得分:0)
我的经验是,如果您想使用myFunc().then(processValue).catchError(handleError);
,则应该返回Future.error而不是抛出它。
答案 1 :(得分:0)
异步和等待是一种语言扩展/语法糖,可以通过恢复同步方式来简化异步代码的使用。
两者都直接取消了期货的使用,使此代码类似:
// On the callee's side
Future<String> calleeAsync() async {
return "from async callee";
}
Future<String> calleeSync() {
return Future.value("from sync callee");
}
// On the caller's side
Future<void> callerAsync() async {
print("got ${await calleeAsync()}");
print("got ${await calleeSync()}");
}
void callerSync() {
calleeAsync()
.then((v) => print("got3 $v"))
.then((_) => calleeSync())
.then((v) => print("got4 $v"));
}
(在callerSync中,第二个then()
的回调可以与第一个回调合并,而第三个then()
也可以由于与monad类似的关联而直接附加到calleeSync()
上)
以相同的方式,这些功能是等效的:
// On the callee's side
Future<void> calleeAsync() async {
throw "error from async";
}
Future<void> calleeSync() {
return Future.error("error from sync");
}
// On the caller's side
Future<void> callerAsync() async {
try {
await calleeAsync();
} catch (e) {
print("caught $e");
}
try {
await calleeSync();
} catch (e) {
print("caught $e");
}
}
void callerSync() {
calleeAsync()
.catchError((e) => print("caught $e"))
.then((_) => calleeSync())
.catchError((e) => print("caught $e"));
}
总而言之,没有实际区别。 return Future.error(…)
根本没有利用 async 函数提供的扩展,因此更像是将两种异步代码混合在一起。