Photo by chansu shin on Unsplash

On this page

Web servers, browsers, and Node all wait on work that finishes later: a DNS lookup, a disk read, a button click. Asynchronous APIs report results through callbacks, promises, or event streams instead of blocking the call stack until the answer arrives.

This series walks the main patterns in order of how most codebases adopt them today. For where async work actually runs on the thread, see The event loop, tasks, and microtasks.

Single value versus stream

Shape Typical API Example
One future value Promise, async function fetch body, readFile result
Many values over time Observable, async iterator, event emitter live quotes, SSE, for await..of on a stream
Sync sequence Iterator, array in-memory list

Pick the smallest abstraction that matches the shape. A single HTTP response rarely needs an Observable; a live ticker rarely fits a single Promise.

Pull versus push

  • Pull — the consumer asks for the next value (iterator.next(), await read()).
  • Push — the producer delivers when ready (timer fires, socket receives bytes, Observable emits).

Promises and async/await are push-then-await: the runtime notifies you when settled. Iterators are pull. Observables are push with optional backpressure patterns in libraries.

Challenges async code introduces

Without careful structure, async programs make it hard to answer:

  • When does data arrive (latency, timeouts)?
  • How much arrives (one packet versus a stream)?
  • Whether it arrives at all (offline host, aborted request)?
  • In what order completions run relative to other tasks (microtasks versus macrotasks)?

The following chapters show concrete tools for each concern.

Roadmap through this series

  1. Callbacks and timers — the original style; still everywhere in host APIs.
  2. Promises in JavaScript — one future value with a shared composition model.
  3. Async/await in JavaScript — synchronous-looking control flow over promises.
  4. Cancellation with AbortController — cooperative cancel for fetch and custom work.
  5. Observables in JavaScript — comparison with promises when many values or unsubscribe matter.

For lazy async sequences, see the Iteration and Generators series.

Continue with Callbacks and timers.

Search articles

Type a word to search published articles.

Open the search page