Promises and async/await
Promises represent the eventual result of an operation. Know how settlement, chaining, the combinators and async/await work, and why promises can't cancel or restart the work behind them.
Key points
- 1
A promise settles once: later
resolve/rejectcalls are ignored. The executor runs synchronously, and a throw inside it becomes a rejection. - 2
Every
then/catch/finallyreturns a new promise. Returned values fulfil it, thrown errors reject it, and returned promises are adopted. Adopting a returned native promise costs two extra microtasks. - 3
allfails fast,allSettledreports every outcome,racecopies the first settlement, andanywaits for the first success or rejects with anAggregateError. None of them cancels the losers. - 4
Async functions always return a promise and run synchronously until the first
await. Insidetry, usereturn awaitso rejections reachcatch. - 5
Start independent work before awaiting it, but combine the promises with
Promise.allso every rejection has a handler. - 6
Cancellation is cooperative: pass an
AbortSignalto APIs that accept one, checksignal.throwIfAborted()in your own loops, and useAbortSignal.timeout/anyfor deadlines. - 7
To retry, call a function again; a promise is a finished result and can't be re-run.
Common traps
array.forEach(async ...)does not wait for the callbacks, and loses their rejections.A timeout built with
Promise.raceleaves the original work running, and in Node.js the timer can keep the process alive.A promise that rejects before anything awaits it is an unhandled rejection. Since Node 15 that crashes the process by default.
Read the source
Test yourself on Promises and async/await
Ten questions, with the answer and explanation after each one.