How to use await outside of an async function in JavaScript

avatar
Borislav Hadzhiev

Last updated: Mar 4, 2024
2 min

banner

# Use await outside of an async function in JavaScript

There are multiple ways to use the await operator outside of an async function:

  1. Use a Node.js version higher than 16.12.0 or set type to module in your package.json file if using Node version 14.8.0 - 16.11.0.
  2. Load the JS script as a module by setting type to module in the script tag.
  3. Use an immediately invoked function expression.

# Using an immediately invoked function expression

Here is the most widely supported approach - using an immediately invoked function expression.

index.js
// ๐Ÿ‘‡๏ธ Example promise const p = Promise.resolve('bobbyhadz.com'); (async () => { try { const value = await p; console.log(value); // ๐Ÿ‘‰๏ธ "bobbyhadz.com" } catch (err) { console.log(err); } })();

using immediately invoked function expression

The code for this article is available on GitHub

Technically, we are defining an async function here, however, we call the function immediately and get access to the resolved value.

If the promise is rejected, the reason for its rejection will be passed to the catch block.

If you're working on the client side, you can check the browser support for the top-level await feature in this caniuse table.

I've also written a detailed guide on how to access the value of a promise.

# Using top-level await in the browser

We can use the top-level await feature by setting the type attribute to module when loading the JS file.

index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> </head> <body> <!-- โœ… type is set to module โœ… --> <script type="module" src="index.js"></script> </body> </html>

This enables us to use top-level await directly.

index.js
const p = Promise.resolve('bobbyhadz.com'); try { const value = await p; console.log(value); // ๐Ÿ‘‰๏ธ "bobbyhadz.com" } catch (err) { console.log(err); }

using top level await in the browser

When using top-level await, it is very important to use a try/catch block because an uncaught exception caused by a rejected promise might stop your application from running.

index.js
// ๐Ÿ‘‡๏ธ Example rejected promise const p = Promise.reject('Something went wrong'); try { const value = await p; console.log(value); } catch (err) { // ๐Ÿ‘‡๏ธ catch the error here console.log(err); // ๐Ÿ‘‰๏ธ "Something went wrong" }
The code for this article is available on GitHub

# Using top-level await in Node.js

If you use Node.js version 16.12.0 or more recent, you can use top-level await directly without changing anything.

If your Node.js version is in the range 14.8.0 - 16.11.0, you need to set the type property to module in your package.json file.

package.json
{ "type": "module", // ...rest }

If your project doesn't have a package.json file, create one by issuing the npm init -y command.

shell
npm init -y

Now you can use top-level await in your Node.js project.

index.js
const num = await Promise.resolve(42); console.log(num); // ๐Ÿ‘‰๏ธ 42
The code for this article is available on GitHub

However, as I previously mentioned, use a try/catch block to make sure you don't crash your application if a Promise is rejected or an error is raised.

index.js
const p = Promise.resolve(42); try { const num = await p; console.log(num); // ๐Ÿ‘‰๏ธ 42 } catch (err) { console.log(err); }

# Additional Resources

You can learn more about the related topics by checking out the following tutorials:

I wrote a book in which I share everything I know about how to become a better, more efficient programmer.
book cover
You can use the search field on my Home Page to filter through all of my articles.

Copyright ยฉ 2024 Borislav Hadzhiev