We are familiar with await in JavaScript, which allows asynchronous promise-based functions to be executed sequentially to make code readable.

// 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);
Copy the code

But according to the syntax specification, await can only appear inside async functions, otherwise an error will be reported.

// 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();
Copy the code

There is nothing wrong with writing this way, but is there a better way to just use await?

Top-level await is available in Node.js v14.8

Node.js v14.8 allows direct use of the top-level await instead of using the –harmony-top-level-await notation.

$node --harmony-top-level-await app.js
Copy the code

The problem with this is that the top-level await can only be used in the ESM; There are three ways to make js scripts ESM.

The.mjs extension

Using the.mjs extension is the simplest way 🎉.

// File: index.mjs
//
// Command line usage: node index.mjs

const asyncMsg = await Promise.resolve('WORKS! ');
console.log(asyncMsg); // "WORKS!"
Copy the code

Set package Type

If you can set “type”: “module” for your package.json,

// 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!"
Copy the code

Input-type (eval)

Sometimes, you might need eval to execute code blocks. In these cases, set input-type to module to specify that the string passed is ESM.

$node --input-type=module \ 
  --eval="const asyncMsg = await Promise.resolve('WORKS! '); console.log(asyncMsg);"
Copy the code

reference

  • Top-level await is available in Node.js modules