Javascript 如何在顶层使用async/await?
我一直在看Javascript 如何在顶层使用async/await?,javascript,node.js,async-await,ecmascript-2017,Javascript,Node.js,Async Await,Ecmascript 2017,我一直在看async/wait,在看了几篇文章之后,我决定自己测试一下。然而,我似乎无法理解为什么这不起作用: 异步函数main(){code> var value=wait Promise.resolve('Hey there'); console.log('内部:'+值); 返回值; } var text=main(); console.log('外部:'+文本); 控制台输出以下内容(节点v8.6.0): >外部:[反对承诺] >里面:嘿,那里 为什么函数中的日志消息会在之后执行?我认为
async
/wait
,在看了几篇文章之后,我决定自己测试一下。然而,我似乎无法理解为什么这不起作用:
异步函数main(){code>
var value=wait Promise.resolve('Hey there');
console.log('内部:'+值);
返回值;
}
var text=main();
console.log('外部:'+文本);
控制台输出以下内容(节点v8.6.0):
>外部:[反对承诺]
>里面:嘿,那里
为什么函数中的日志消息会在之后执行?我认为创建async
/await
的原因是为了使用异步任务执行同步执行
是否有一种方法可以使用函数中返回的值而不使用.then()
之后的main()
我似乎无法理解为什么这不起作用
因为main
返回一个承诺;所有的async
函数都可以
在顶层,您必须:
async
函数(除非您希望出现“未处理的拒绝”错误),或然后
和捕获
,或wait
async
函数
注意捕捉
;您必须处理承诺拒绝/异步异常,因为其他任何情况都不会发生;你没有电话可以转告。如果愿意,您可以通过catch
函数(而不是try
/catch
语法)调用它的结果来执行此操作:
…更简洁一点(我喜欢这样)
当然,也可以不处理错误,只允许出现“未处理的拒绝”错误
#2-然后
和捕获
如果链或then
处理程序中发生错误,将调用catch
处理程序。(确保您的catch
处理程序不会抛出错误,因为没有注册任何内容来处理这些错误。)
或的两个参数,然后:
main().then(
text => {
console.log(text);
},
err => {
// Deal with the fact the chain failed
}
);
再次注意,我们正在注册一个拒绝处理程序。但是在这个表单中,请确保then
回调都不会抛出任何错误,没有注册任何内容来处理它们
#3模块中的顶级等待
您不能在非模块脚本的顶层使用wait
,但()允许您在模块的顶层使用它。这类似于使用顶级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
}
请注意,如果您这样做,从您的模块导入的任何模块都将等待,直到您等待的承诺解决;当对使用顶级wait
的模块进行求值时,它基本上会向模块加载器返回一个承诺(就像async
函数所做的那样),模块加载器会等待该承诺得到解决,然后再对依赖它的任何模块体进行求值。因为main()
异步运行,所以它会返回一个承诺。您必须在then()
方法中获得结果。因为then()
也返回promise,所以必须调用process.exit()
来结束程序
main()
.then(
(text) => { console.log('outside: ' + text) },
(err) => { console.log(err) }
)
.then(() => { process.exit() } )
这个问题的实际解决办法是以不同的方式处理
您的目标可能是某种初始化,这种初始化通常发生在应用程序的顶层
解决方案是确保在应用程序的顶层只有一条JavaScript语句。如果在应用程序的顶部只有一条语句,则可以在任何其他位置自由使用async/Wait(当然要遵守正常语法规则)
换句话说,将整个顶层封装在一个函数中,这样它就不再是顶层,从而解决了如何在应用程序的顶层运行异步/等待的问题—您不需要
这是应用程序的顶级外观:
import {application} from './server'
application();
要在当前答案的基础上提供更多信息:
node.js
文件的内容当前以类似字符串的方式连接在一起,以形成函数体
例如,如果您有一个文件test.js
:
// Amazing test file!
console.log('Test!');
然后,node.js
将秘密连接一个函数,如下所示:
function(require, __dirname, ... perhaps more top-level properties) {
// Amazing test file!
console.log('Test!');
}
需要注意的主要问题是,生成的函数不是异步函数。因此,您不能直接在其内部使用术语wait
但是如果您需要处理此文件中的承诺,那么有两种可能的方法:
不要直接在函数内部使用wait
不要使用wait
选项1要求我们创建一个新的作用域(这个作用域可以是async
,因为我们可以控制它):
选项2要求我们使用面向对象的promise API(不太漂亮但功能相同的promises工作范例)
看到node添加对顶级wait
的支持会很有趣 已进入第3阶段,因此您的问题的答案是如何在顶层使用async/await?只需添加wait
调用main()
:
异步函数main(){
var value=wait Promise.resolve('Hey there');
console.log('内部:'+值);
返回值;
}
var text=await main();
console.log('外部:'+文本)
或者只是:
const text=wait Promise.resolve('Hey there');
控制台
import {application} from './server'
application();
// Amazing test file!
console.log('Test!');
function(require, __dirname, ... perhaps more top-level properties) {
// Amazing test file!
console.log('Test!');
}
// Amazing test file!
// Create a new async function (a new scope) and immediately call it!
(async () => {
await new Promise(...);
console.log('Test!');
})();
// Amazing test file!
// Create some sort of promise...
let myPromise = new Promise(...);
// Now use the object-oriented API
myPromise.then(() => console.log('Test!'));