unicorn/prefer-top-level-await

Require top-level await instead of promise chains and async wrappers at the top of a module

A module can use await outside of a function. An async wrapper or a .then() chain at the top level is more code for the same work. Modules that import the file don't wait for it, and a rejection becomes an unhandled rejection instead of a failed import.

The rule reports three things outside of functions and classes:

  • a call to .then(), .catch() or .finally() that isn't awaited
  • an async function that's called right where it's written
  • a call to an async function declared in the file, if that call is the only place it's used

Configure#

Off by default. To turn it on:

bunfig.toml
[lint.rules]
"unicorn/prefer-top-level-await" = "error" # or "warn"

Examples#

example.js3 problems
(async () => {
  await connect();
})();

loadConfig().then(config => start(config));

async function main() {
  await migrate();
}
main();
example.jsNo problems
await connect();

const config = await loadConfig();
start(config);

await migrate();

const [users, posts] = await Promise.all([loadUsers().catch(() => []), loadPosts()]);

When not to use it#

Top-level await is a syntax error in CommonJS, and the rule doesn't look at how a file is loaded. It reports this in main.cjs too:

main.cjs1 problem
loadConfig().then(config => start(config));

Turn the rule off for files that are loaded as CommonJS.