Promise
JavaScript's object for a value that will arrive later, how it replaced nested callbacks, and the microtask queue that decides when its handlers run.
A promise is an object standing in for a value that isn't available yet: the result of a network request or a timer. It starts pending and settles exactly once, either fulfilled with a value or rejected with an error. Code attaches handlers with .then and .catch, or waits for it with await, and the handlers run when the promise settles, or right away if it already has.
The idea is older than JavaScript. Computer scientists described futures and promises in the late 1970s as placeholders for results computed concurrently. JavaScript adopted them from community libraries, and the Promises/A+ specification of 2012 defined interoperable behavior so that any thenable, any object with a then method, could work with any other. Native promises arrived in ES2015, and async/await in ES2017 made them read like ordinary sequential code.
Promises solved callback hell. Before them, asynchronous JavaScript passed a function to be called on completion, and a sequence of dependent steps nested each callback inside the last, drifting rightward into the "pyramid of doom" with error handling repeated at every level. A promise chain stays flat, and one .catch at the end handles a failure anywhere above it. Combinators handle groups: Promise.all waits for every promise and fails fast, and race takes the first to finish.
When handlers run is set by the microtask queue. The Event Loop runs one task at a time, such as an event handler or a timer callback. After each task, and before the browser renders, it drains every queued microtask, and promise handlers are microtasks. So a resolved promise's .then runs before any pending timer or input event, even a timer set for zero milliseconds. The flip side is that code queueing microtasks endlessly starves rendering completely, a Long Task in disguise.
Several sharp edges remain:
- Promises are eager. The work starts when the promise is created, not when someone awaits it. Two separate
awaits in a row run in sequence, so independent requests should start together and be awaited withPromise.all, or they form a needless waterfall. - No cancellation. A promise can't be stopped once started. Cancellation is a separate signal, usually an
AbortControllerpassed alongside the work. - Unhandled rejections. A rejected promise with no handler used to fail silently. Browsers now log it, and Node.js since version 15 crashes the Process by default, treating it as the bug it usually is.
- Ordering assumptions. Async code that assumes one request finishes before another invites a Race Condition, and Optimistic UI must handle the case where the server answers out of order.
Promises resemble a Monad, since then both maps and flattens, though they don't obey the laws strictly: a promise can never contain another promise.
See also2
Iterator
An object that hands out the elements of a collection or sequence one at a time on request, separating how a sequence is produced from how it's consumed, which lets the same loop walk arrays, trees, files and infinite streams.
Computation & Algorithms7 connections
Web Worker
A background thread for running JavaScript off the main thread, with no access to the DOM.
Web Platform12 connections
Linked from7
- Event LoopComputation & Algorithms
A single-threaded runtime's mechanism for pulling the next callback off a queue once the call stack is empty.
- IteratorComputation & Algorithms
An object that hands out the elements of a collection or sequence one at a time on request, separating how a sequence is produced from how it's consumed, which lets the same loop walk arrays, trees, files and infinite streams.
- JavaScriptWeb Platform
The programming language of the web browser, written in ten days in 1995, standardized as ECMAScript, and now run everywhere from servers to build tools despite quirks it can never remove.
- MonadComputation & Algorithms
A wrapper type with a way to lift a value in and a way to chain functions that return more wrappers.
- Optimistic UIWeb Platform
Updating the UI as if a server request has already succeeded, before the server has actually responded.
- Web Animations APIWeb Platform
A browser interface that exposes the engine behind CSS animations and transitions to JavaScript, giving scripts animations they can pause, reverse, seek, and await, while still running smoothly off the main thread.
- Web WorkerWeb Platform
A background thread for running JavaScript off the main thread, with no access to the DOM.