我已经复习了async
/await
,在复习了几篇文章之后,我决定自己测试一下。然而,我似乎无法理解为什么这不起作用:
async function main() {
var value = await Promise.resolve('Hey there');
console.log('inside: ' + value);
return value;
}
var text = main();
console.log('outside: ' + text);
控制台输出以下内容(节点V8.6.0):
>外:“对象承诺”
>内部:嘿那里
为什么函数内部的日志消息会在之后执行?我认为创建async
/await
的原因是为了使用异步任务执行同步执行。
有没有一种方法可以使用函数内部返回的值,而不用.then()
后面的main()
?
我似乎无法理解为什么这不起作用。
因为main
返回一个承诺;所有async
函数都可以。
在最高层,您必须:
>
使用从不拒绝的顶级async
函数(除非您希望出现“未经处理的拒绝”错误),或者
使用then
和catch
,或
(马上就要来了!)使用顶级await
,这是一个已达到流程第3阶段的建议,允许在模块中顶级使用await
。
(async () => {
try {
var text = await main();
console.log(text);
} catch (e) {
// Deal with the fact the chain failed
}
})();
注意catch
;您必须处理承诺拒绝/异步异常,因为其他的都不会处理;您没有可将它们传递给的呼叫者。如果您愿意,可以通过catch
函数(而不是try
/catch
语法)调用它的结果来实现:
(async () => {
var text = await main();
console.log(text);
})().catch(e => {
// Deal with the fact the chain failed
});
...更简洁一点(因为这个原因我喜欢它)。
或者,当然,不处理错误,只允许“未处理拒绝”错误。
main()
.then(text => {
console.log(text);
})
.catch(err => {
// Deal with the fact the chain failed
});
如果在链或您的then
处理程序中发生错误,将调用catch
处理程序。(请确保catch
处理程序不会抛出错误,因为没有注册任何内容来处理错误。)
或then
的两个参数:
main().then(
text => {
console.log(text);
},
err => {
// Deal with the fact the chain failed
}
);
再次注意,我们正在注册一个拒绝处理程序。但是在这种形式下,请确保您的then
回调都没有抛出任何错误,没有注册任何内容来处理它们。
您不能在非模块脚本的顶层使用await
,但顶层await
建议(阶段3)允许您在模块的顶层使用它。这与使用顶级async
函数包装器(上面的#1)类似,因为您不希望顶级代码拒绝(抛出错误),因为这将导致未处理的拒绝错误。因此,除非您希望在发生错误时进行未经处理的拒绝(如#1),否则您希望将代码包装在错误处理程序中:
// In a module, once the top-level `await` proposal lands
try {
var text = await main();
console.log(text);
} catch (e) {
// Deal with the fact the chain failed
}
请注意,如果您这样做,任何从您的模块导入的模块都将等待,直到您的await
ing承诺解决为止;当使用顶级await
的模块被评估时,它基本上会向模块加载器返回一个承诺(就像async
函数所做的那样),该模块加载器会等待该承诺被确定,然后再评估依赖于它的任何模块的主体。