Read first

A promise is a placeholder for a value that will arrive later. It starts pending and then settles exactly once: fulfilled with a value, or rejected with a reason (usually an Error). After it settles, it never changes.

How it works

  • new Promise((resolve, reject) => { ... }): the function you pass (the executor) runs immediately and synchronously. Only the delivery of the result is later.
  • .then(onFulfilled, onRejected) registers callbacks and returns a new promise, which is how chains work. Whatever a callback returns becomes the next promise’s value; if it throws, the next promise rejects.
  • Callbacks always run as microtasks, even when the promise is already settled.

Combining promises

MethodSettles whenRejects when
Promise.all([...])all fulfill (gives an array of values, in input order)any rejects (fail fast)
Promise.allSettled([...])all settle (gives {status, value / reason} objects)never
Promise.race([...])the first one settles, either waythe first one rejects
Promise.any([...])the first one fulfillsall reject (AggregateError)
const wait = (ms, v) => new Promise((r) => setTimeout(() => r(v), ms));
Promise.all([wait(30, 'a'), wait(10, 'b')]).then((v) => console.log(v));   // [ 'a', 'b' ]  (input order, not finish order)
Promise.race([wait(30, 'a'), wait(10, 'b')]).then((v) => console.log(v));  // b

Traps

  • A rejected promise nobody handles becomes an “unhandled rejection” (in Node 15+ this crashes the process by default).
  • Forgetting to return inside a .then breaks the chain: the next step gets undefined and doesn’t wait.
  • A promise does not make work run in parallel or on another thread. See concurrency-vs-parallelism.

async-await is syntax built on promises.

Check yourself

Leads to

  • async / await: Syntax that lets promise-based code read top to bottom. An async function always returns a promise; await pauses only that function.
  • Microtask queue: A high-priority queue for promise callbacks and await continuations. It is emptied completely after every task.