The javascript await operator waits for a Promise (or thenable) to settle and returns the fulfilled value inside an async function—or at the top level of an ES module. Pairing js await with async is the usual way to write async await javascript that reads like synchronous control flow. For how promises resolve and reject in the first place, see JavaScript Promise.resolve and JavaScript Promise.reject.
Tested on: all examples in this tutorial were run with Node.js v20.18.2, and the output shown below each snippet is its exact console output. Examples use
setTimeout(..., 0)so you can reproduce results quickly; real code might use larger delays orfetch.
Quick reference
Use this table for where await javascript is valid and for picking sequential vs concurrent await patterns.
| Context | await allowed? |
|---|---|
Inside async function |
Yes |
| Top level of ES module | Yes |
Non-async function / classic script |
No (SyntaxError) |
Basic await promise inside async
Inside an async function, await pauses that function until the promise fulfills (or throws on rejection).
async function example() {
const myPromise = new Promise((resolve) => {
setTimeout(() => {
resolve("hello world");
}, 0);
});
const result = await myPromise;
console.log(result);
}
example();hello worldTwo awaits in a row — sequential timing
Each await waits for its promise before the next line runs. If each delay were 2000 ms, the total would be about 4 seconds, not two—use Promise.all when the work is independent (see below).
async function sequentialExample() {
const promise1 = new Promise((resolve) => {
setTimeout(() => resolve("hello"), 0);
});
const promise2 = new Promise((resolve) => {
setTimeout(() => resolve("world"), 0);
});
const result1 = await promise1;
const result2 = await promise2;
console.log(result1 + " " + result2);
}
sequentialExample();hello worldPromise.all — concurrent await
Start independent promises first, then await Promise.all([...]) so they run concurrently and you still get ordered results in one step.
async function parallelExample() {
const p1 = Promise.resolve("hello");
const p2 = Promise.resolve("world");
const [a, b] = await Promise.all([p1, p2]);
console.log(a + " " + b);
}
parallelExample();hello worldtry / catch with await — rejections
Rejected promises from await propagate like thrown values inside the async function, so wrap risky awaits in try/catch (or handle with .catch on the promise).
async function mayFail() {
try {
await Promise.reject(new Error("bad"));
} catch (e) {
console.log(e.message);
}
}
mayFail();badawait on a non-promise (await operator javascript)
Non-promise values are wrapped with Promise.resolve semantics, so await 5 still yields 5.
async function num() {
console.log(await 5);
}
num();5Top-level await — ES modules only
Top level await javascript is allowed at module scope in ES modules. Save as a .mjs file (or set "type": "module" in package.json) and run with node:
const x = await Promise.resolve(42);
console.log(x);42In a classic script without modules, use an async IIFE instead:
(async () => {
const x = await Promise.resolve(42);
console.log(x);
})();42Summary
- Use
awaitonly insideasyncfunctions or at the top level of ES modules; otherwise you get aSyntaxError. - Sequential
awaitruns one settlement after another; usePromise.all(or related helpers) when tasks are independent. - Handle rejections with
try/catcharoundawaitor explicit.catchon the promise chain. awaiton a non-promise usesPromise.resolvesemantics; top-levelawaitneeds a module context or an async IIFE in classic scripts.
References
MDN references for the await operator, async function, and concurrent waiting with Promise.all.
