async and await are a nicer way to use promises. Code that waits reads top to bottom, like normal code.
const wait = ms => new Promise(resolve => setTimeout(resolve, ms));
async function run() {
console.log("start");
await wait(300); // pause here until the promise settles
console.log("300 ms later");
return "finished";
}
run().then(result => console.log(result)); // → finished
The two keywords
asyncbefore a function means “this function returns a promise, and can useawaitinside”.awaitbefore a promise means “pause this function until the promise settles, then give me its result”.
While the function is paused, the rest of the page keeps running. Only that function waits.
Getting values
const wait = ms => new Promise(resolve => setTimeout(resolve, ms));
function getUser(id) {
return wait(100).then(() => ({ id, name: "Maya" }));
}
async function showUser() {
const user = await getUser(1); // user is the resolved value, not a promise
console.log(user.name); // → Maya
}
showUser();
Compare with the then version:
getUser(1).then(user => console.log(user.name));
For one step they are similar. With several dependent steps, await is much clearer:
const wait = ms => new Promise(resolve => setTimeout(resolve, ms));
const getUser = () => wait(50).then(() => ({ id: 1 }));
const getPosts = user => wait(50).then(() => ["Post A", "Post B"]);
async function main() {
const user = await getUser();
const posts = await getPosts(user);
console.log(posts); // → ["Post A", "Post B"]
}
main();
An async function always returns a promise
async function five() { return 5; }
console.log(five()); // a Promise
five().then(v => console.log(v)); // → 5
Where can you use await?
- Inside an
asyncfunction. - At the top level of an ES module (top-level
await).
Using await in a normal function is a syntax error.
async arrow functions and event handlers
<button id="go">Load</button>
<p id="out"></p>
<script>
const wait = ms => new Promise(r => setTimeout(r, ms));
document.querySelector("#go").addEventListener("click", async () => {
document.querySelector("#out").textContent = "Loading…";
await wait(600);
document.querySelector("#out").textContent = "Loaded!";
});
</script>
await does not make code blocking
It only pauses the async function it is in. It is not the same as a busy loop that freezes the page.
Common mistake: forgetting await
const wait = ms => new Promise(resolve => setTimeout(() => resolve("data"), ms));
async function main() {
const withoutAwait = wait(50);
console.log(withoutAwait); // a Promise, not "data"
const withAwait = await wait(50);
console.log(withAwait); // → data
}
main();
If you see Promise {} where you expected a value, you probably forgot await.
Errors
async function you handle errors with try...catch. That is the topic of the next lesson: Error Handling in async Code.