async/await is syntax over promises that lets asynchronous code read top-to-bottom like synchronous code — with ordinary try/catch for errors.
The rules
An
asyncfunction always returns a promise — a returned value is wrapped, a thrown error becomes a rejection.await ppauses that function (not the thread) untilpsettles, then returns the value or throws the reason.awaitworks insideasyncfunctions and at the top level of ES modules.
async function getNumber() { return 7; }
async function explode() { throw new Error("async boom"); }
console.log(getNumber() instanceof Promise);
console.log(await getNumber());
try {
await explode();
} catch (e) {
console.log("caught:", e.message);
}true
7
caught: async boomRewriting a promise chain
const db = {
user: (id) => new Promise((r) => setTimeout(() => r({ id, name: "Asha" }), 5)),
orders: (user) => new Promise((r) => setTimeout(() => r([{ total: 30 }, { total: 12 }]), 5)),
};
// with then
db.user(1)
.then((user) => db.orders(user).then((orders) => ({ user, orders })))
.then(({ user, orders }) => console.log("then:", user.name, orders.length));
// with async/await
async function summary(id) {
const user = await db.user(id);
const orders = await db.orders(user);
const total = orders.reduce((s, o) => s + o.total, 0);
return `${user.name} spent ${total}`;
}
console.log("await:", await summary(1));then: Asha 2
await: Asha spent 42Do not serialise independent work
const fetchA = () => new Promise((r) => setTimeout(() => r("A"), 30));
const fetchB = () => new Promise((r) => setTimeout(() => r("B"), 30));
let t = performance.now();
const a1 = await fetchA();
const b1 = await fetchB(); // waits for A first: ~60 ms
const slow = performance.now() - t;
t = performance.now();
const [a2, b2] = await Promise.all([fetchA(), fetchB()]); // concurrently: ~30 ms
const fast = performance.now() - t;
console.log(a1 + b1, a2 + b2, slow > 55, fast < 50);AB AB true trueawait in loops
const double = (n) => new Promise((r) => setTimeout(() => r(n * 2), 5));
const nums = [1, 2, 3];
const wrong = nums.forEach(async (n) => await double(n)); // forEach ignores promises
console.log("forEach returns:", wrong);
const out = [];
for (const n of nums) out.push(await double(n)); // sequential, correct
console.log(out, await Promise.all(nums.map(double))); // parallel, correctforEach returns: undefined
[ 2, 4, 6 ] [ 2, 4, 6 ]Error handling patterns
const risky = (ok) => (ok ? Promise.resolve("data") : Promise.reject(new Error("network")));
// 1. try / catch / finally
async function load() {
try {
return await risky(false); // `return await` so the catch applies
} catch (e) {
return `fallback (${e.message})`;
} finally {
console.log("hide spinner");
}
}
console.log(await load());
// 2. Go-style tuple helper
const to = (p) => p.then((v) => [null, v], (e) => [e, null]);
const [err, data] = await to(risky(true));
console.log(err, data);hide spinner
fallback (network)
null dataWhat does an async function return?
Does await block the thread?