Dan D Kim

Let's share stories

Node 14.8 New Feature - Top Level Await

2020-08-17 Dan D. Kimjavascript

On Aug 11th 2020, Node v14.8.0 was released. Release docs.

What I love about it? Top-level Awaits.

Top-Level Await

You can check out V8.dev's feature announcement from back in Oct 8 2019.

Basically, if you have an await outside of the async function, you would run into a Syntax error.

// someModule.js

await Promise.resolve(console.log('Hi'))
// Syntax error: await is only valid in async function

The workaround was to use Immediately Invoked Function Expressions (IIFE).

// someModule.js

(async () => {
  await Promise.resolve(console.log('Hi'))
})()
// Hi

Now, within modules and modules only we can use await outside of the async functions.

// someModule.js

await Promise.resolve(console.log('Hi'))
// Hi

No more of that IIFE workaround!

Benefit

The benefit of this feature is that we don’t have to rely on IIFE.

What’s the problem with IIFE? It makes graph execution and analyzability obscure, espcially when we are forced to use it as the only workaround, and not necessarily for the benefits of IIFE.

Risk

A top-level circular dependency can introduce a deadlock. :/

New features = new opportunities for bugs.

Cocktail conversation

The Javascript engine executes modules using a post-order traversal. That means modules from the leftest node of the dependency tree are evaluated first, then their siblings, then their parents… until the top root node is evaluated.

The order of module execution was deterministic. Guaranteed. But with top-level await, it is no longer the case.

With top-level await, modules are still executed in the same post-order fashion, but the execution of a module can be deferred until an awaited promise is resolved. This means that the sibling modules can continue their execution without being hung up on the await of their leftest sibling(s). This addresses the concern of blocking execution.

On that note, parent modules also defer their execution for the await of all their children modules.

There is another concern - does top-level await block fetching of resources?

Answer is no. Top-level await happens in the execution phase of the module, meaning all resources have already been fetched at this point.


That’s all. Happy programming! :)