JS Async/Await
async and await are sugar on top of Promises. They let you write asynchronous code that reads top-to-bottom, like ordinary synchronous code.
Two keywords
| Keyword | What it does |
|---|---|
async | Marks a function as asynchronous. Its return value is always wrapped in a Promise. |
await | Inside an async function, pauses until the Promise settles, then returns the value (or throws the rejection). |
From .then to await
JS
// .then chain
function loadUser(id) {
return fetch(`/api/users/${id}`)
.then(res => res.json())
.then(user => { console.log(user); return user; })
.catch(err => console.error(err));
}
// async/await — same behaviour
async function loadUser(id) {
try {
const res = await fetch(`/api/users/${id}`);
const user = await res.json();
console.log(user);
return user;
} catch (err) {
console.error(err);
}
}
Common patterns
| Pattern | Code |
|---|---|
| Sequential (one waits on the previous) | const a = await fnA(); const b = await fnB(a); |
| Parallel (independent work) | const [a, b] = await Promise.all([fnA(), fnB()]); |
| Catch errors | Wrap in try/catch, or chain .catch() on the call site. |
| Always run cleanup | try { … } finally { cleanup(); } |
Top-level await (modules)
app.js (ES Module)
// Inside a module file, you can await at the top level
const config = await fetch("/config.json").then(r => r.json());
export default config;
Performance gotcha: consecutive
awaits on independent calls happen in series. Reach for Promise.all whenever the calls don't depend on each other — it's the most common performance bug in modern JS code.Example
Example
<!DOCTYPE html>
<html>
<body>
<p id="out"></p>
<script>
document.getElementById("out").textContent = "Hello from JS Async/Await!";
</script>
</body>
</html>
Try it Yourself »
Exercise
Wait for the fetch to resolve before reading the body.
const res =
fetch('/api');
Five letters — only valid inside async functions.
Discussion
Loading…