async and await
Chains of then() quickly become unwieldy. The async and await keywords let you write asynchronous code as if it were ordinary: top to bottom, line by line. Underneath it is the same promises, just written more briefly.
await
The await keyword before a promise pauses the code until the promise is fulfilled and returns its result:
const value = await Promise.resolve(42);
console.log(value); // 42The result sits in a plain variable — no then() and no nested function.
async
Inside functions, await works only if the function is declared with the async keyword. Such a function always returns a promise, even if it says return 42:
async function getAnswer() {
return 42;
}
const answer = await getAnswer();
console.log(answer); // 42You can also write await outside functions — in modules and in the examples on this site. In a plain browser script it does not work outside a function.
Waiting step by step
When there are several actions, code with await reads like a plain sequence:
const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
async function cook() {
console.log('Putting the kettle on');
await wait(500);
console.log('The kettle has boiled');
await wait(300);
console.log('The tea is ready');
}
await cook();
// Putting the kettle on
// The kettle has boiled
// The tea is readyEach await waits for its promise, yet the page does not freeze: while the function waits, other code runs.
Errors
If a promise is rejected, await throws the error like an ordinary throw. Catch it with try...catch:
async function load() {
throw new Error('The server is not responding');
}
try {
await load();
} catch (error) {
console.log(error.message); // The server is not responding
}A finally block works too: it runs after both success and failure.
Running things at the same time
await after await performs actions one by one. If they do not depend on each other, it is faster to start them all at once and wait for them with Promise.all():
const wait = (value, ms) => new Promise((resolve) => setTimeout(() => resolve(value), ms));
const start = Date.now();
const [first, second] = await Promise.all([wait('a', 300), wait('b', 300)]);
console.log(first, second); // a b
console.log(Date.now() - start < 500); // trueTwo waits of 300 ms took about 300 ms, not 600.
An async function returns a promise
You can also get an async function's result with then() — it is an ordinary promise. This is done where await is not available:
async function getName() {
return 'Anna';
}
getName().then((name) => console.log(name)); // AnnaCommon mistake
If you forget await, the variable holds a promise rather than the result:
async function getAnswer() {
return 42;
}
const answer = getAnswer();
console.log(answer instanceof Promise); // true
console.log(answer + 1); // [object Promise]1There is no error; the program simply behaves incorrectly — which is why this slip is hard to notice.