相关文章推荐
私奔的火车  ·  flutter, ...·  1 年前    · 
2,493

在 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
  • 前端 @北京
    粉丝