在 JavaScript 中
await
想必大家并不陌生,它可以将基于 Promise 的异步函数顺序式执行,使代码具有可读性。
// promise-based code
Promise.resolve('hello world').then((asyncMsg) => {
console.log(msg);
// async/await code
const asyncMsg = await Promise.resolve('hello world');
console.log(msg);
但是根据语法规格,await
只能出现在 async
函数内部,否则会报错。
// use an async IIFE
(async () => {
const asyncMsg = Promise.resolve('hello world');
console.log(asyncMsg);
})();
// use an async main function
async function main() {
const asyncMsg = Promise.resolve('hello world');
console.log(asyncMsg);
main();
虽然这样写并没有什么不好,不过我们仅仅是想使用 await
,有没有更好的办法呢?
顶层 await 在 Node.js v14.8 可用
Node.js v14.8 版本中允许直接使用顶层 await,替代了之前使用 --harmony-top-level-await 标识的方案。
$node --harmony-top-level-await app.js
这有个问题,顶层 await 只能在 ESM 中使用;有三种方式可以使 js 脚本成为 ESM。
一、 .mjs 扩展名
使用 .mjs
扩展名是最简洁的方式 🎉。
// File: index.mjs
// Command line usage: node index.mjs
const asyncMsg = await Promise.resolve('WORKS!');
console.log(asyncMsg); // "WORKS!"
二、 设置 package type
如果你可以为你的 package.json
设置 "type": "module"
,
// File: index.js
// (near package.json including { "type": "module" })
// Command line usage: node index.js
const asyncMsg = await Promise.resolve('WORKS!');
console.log(asyncMsg); // "WORKS!"
三、eval 形式,定义 input-type
有时,你可能需要 eval 执行代码块。在这些情况下,将 input-type
设置为 module 来指定传递的字符串是 ESM。
$node --input-type=module \
--eval="const asyncMsg = await Promise.resolve('WORKS!'); console.log(asyncMsg);"
Top-level await is available in Node.js modules
前端 @北京