Futures and promises
An object that stands for a value that doesn’t exist yet, which you can pass around, wait on or chain more work onto.
How they work
Instead of taking a callback, the operation returns a placeholder at once: a future or promise that will later hold the value or the error. Daniel Friedman and David Wise proposed the term “promise” in 1976; Henry Baker and Carl Hewitt’s 1977 “call-by-future” bound each argument of a function to a separate process, a “future”, evaluating it in parallel. Barbara Liskov and Liuba Shrira’s 1988 promises were built for asynchronous remote calls: the caller keeps running and later claims the result, including any exception, in a type-safe way.
Because the placeholder is a value, futures compose. Java’s Future (Java 5) offers get(), which waits if necessary for the result, so it still blocks a thread; CompletableFuture (Java 8) chains callbacks instead. JavaScript’s Promise.all combines many promises into one that fulfils when all of them do, or rejects with the first rejection.
Chaining with then is cleaner than nesting callbacks but still splits one piece of logic into many small functions, which is what async/await was invented to hide. A JavaScript promise is close to a monad; see the monads concept.
Sources
- Wikipedia: Futures and promises (Friedman and Wise 1976; Java 5; F# asynchronous workflows)
- Baker and Hewitt: The Incremental Garbage Collection of Processes (MIT AI Lab Working Paper 149, June 1977), call-by-future
- Liskov and Shrira: Promises, linguistic support for efficient asynchronous procedure calls in distributed systems (PLDI 1988)
- Java SE 21 API: Future (get waits for the result; since 1.5)
- Java SE 21 API: CompletableFuture (since 1.8)
- MDN: Promise.all() (fulfills when all fulfill, rejects on the first rejection)