Top-level await is available in Node.js modules
source link: https://www.stefanjudis.com/today-i-learned/top-level-await-is-available-in-node-js-modules/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Top-level await is available in Node.js modules
This post is part of my Today I learned series in which I share all my learnings regarding web development.
Node.js is a beautiful tool to write quick utility scripts. I use it in many of my build processes. Renaming files, downloading data, image processing – Node.js scripts handle many tasks in my projects.
There has been one tiny annoyance, though. When dealing with asynchronous functionality such as making network requests, there was no top-level await support in Node.js (yet).
await
allows you to untangle Promises-based code and make it more 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);
Unfortunately, you could not use the await
keyword without wrapping it in an async
function.
// 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();
And while this wrapping is not terrible, its whole purpose is to enable the await
keyword. Is there a better way? Can we avoid these async
wrappers in Node.js code? Top-level await to the rescue!
top-level await
is available "unflagged" in Node.js since v14.8
Starting with Node.js v14.8
, top-level await is available (without the use of the --harmony-top-level-await
command line flag).
There's one catch: top-level await is only available in ES modules. There are three ways to make a Node.js script an EcmaScript module.
But before diving right in, be aware that if you're enabling ES modules in Node.js you have to change all require
and module
statements with their import
and export
counterparts. 🙈
Use the mjs
file extension
Use the .mjs
file extension and call it a day! 🎉
// File: index.mjs
//
// Command line usage: node index.mjs
const asyncMsg = await Promise.resolve('WORKS!');
console.log(asyncMsg); // "WORKS!"
Make the whole package a module
If you're developing a package you can also define the type
property in 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!"
Define input-type
when evaluating string input
Sometimes you might need to pipe code into the Node.js binary or use the eval
flag. Use the input-type
flag to specify that the passed string value is an ES module in these situations.
node --input-type=module \
--eval="const asyncMsg = await Promise.resolve('WORKS!'); console.log(asyncMsg);"
Await, await, await...
This functionality is beautiful! I'll probably stick to the .mjs
file extension for my scripts. Renaming a script file from js
to mjs
is quickly done and is not introducing significant changes.
If you like these quick tips, I send out a weekly newsletter. 👇
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK