About Posts Series Contact
JavaScript 8 min read

Promises in Depth - Series Intro

A complete guide to JavaScript Promises — from why they exist to building a spec-compliant polyfill from scratch. 30 posts covering everything a JavaScript developer needs to truly understand async.

Honey Sharma

JavaScript runs on a single thread. Yet somehow, it fetches data, reads files, waits on timers, and handles user input — all without freezing. The mechanism that makes this possible is async programming, and at the centre of modern async JavaScript sits the Promise.

But most developers learn Promises the same way — a quick tutorial, a few .then() calls, switch to async/await, and move on. That works until it doesn’t. Until you hit a silent swallow, a broken chain, a forEach that refuses to wait, or an error that disappears into the void.

This series exists to close that gap.

Over 30 posts, we go from the very ground up — what the JavaScript event loop actually does, why callbacks fell short, and exactly what problem Promises were designed to solve — all the way to reading the Promises/A+ specification and implementing a fully compliant Promise from scratch in vanilla JavaScript. And for those gearing up for interviews, the final part is dedicated entirely to that.

Whether you are preparing for interviews, debugging async code in production, or just want to actually understand what happens when you write new Promise(), this series is for you.


How This Series Is Structured

The 30 posts are grouped into 8 parts. Each part builds on the previous one, but most posts are self-contained enough to jump into directly if you already know the surrounding context.


Part I — The Problem Space

Before writing a single line of Promise code, it’s worth understanding what world Promises were born into, and why that world needed them.

#PostDescription
01The World Before PromisesThe JavaScript event loop, the call stack, and what it means to be single-threaded
02Callbacks — The Original Async PatternHow callbacks work, callback hell, and the inversion of control problem
03What Promises Set Out to SolveThe mental model of a future value, and the history from jQuery Deferreds to the spec

Part II — Core Mechanics

The beating heart of the series. This is where you learn exactly how a Promise works, not just how to use one.

#PostDescription
04Anatomy of a PromiseThe three states, one-way state transitions, the executor, and what resolve/reject actually do
05Consuming Promises with .then()The .then() signature, return values, why it always returns a new promise, and microtask scheduling
06Error Handling and Cleanup — .catch() and .finally()How rejections propagate, recovering mid-chain, unhandled rejections, and .finally() gotchas
07Promise Chaining In DepthSequential async pipelines, thenable flattening, common chaining mistakes, and flat vs nested chains

Part III — The Promise API

Every static method on the Promise constructor deserves its own focused treatment. Each combinator has distinct semantics that are worth understanding deeply.

#PostDescription
08Promise.resolve() and Promise.reject()Pre-settled promises, wrapping thenables, and the identity shortcut
09Promise.all()Parallelising independent operations, fail-fast behaviour, and ordering guarantees
10Promise.allSettled()Running promises regardless of individual failures and building resilient multi-fetch patterns
11Promise.race()First-settled-wins semantics, timeout wrappers, and why losing promises aren’t cancelled
12Promise.any()First-fulfilled-wins, AggregateError, and how to choose between any, race, and all

Part IV — Promises and async/await

async/await is not a different system — it’s Promises with nicer syntax. This post makes that concrete, and covers the traps that the syntax sugar can hide.

#PostDescription
13async/await — The Full PictureWhat async functions return, how await suspends execution, translating between chains and await, accidental serialisation in loops, the await in forEach trap, floating promises, and top-level await

Part V — Patterns and Recipes

The practical half of the series. Real patterns used in real codebases, explained from first principles so you can adapt them — not just copy them.

#PostDescription
14Execution Patterns and Concurrency ControlSequential tasks with reduce, parallelising with Promise.all, and building a promise pool / concurrency limiter from scratch
15Retry, Timeout, and Fallback PatternsExponential backoff, timeout wrappers with Promise.race, circuit breakers, and waterfall fallbacks
16Deferred Pattern and Promise FactoriesSeparating resolve/reject from the executor, lazy promises, and memoising async calls
17Cancellation — The Gap Promises LeaveWhy the spec has no cancellation, AbortController in practice, and cooperative cancellation in chains
18Promisifying Callback-based APIsWriting promisify by hand, util.promisify in Node.js, and promisifying event emitters

Part VI — Limitations and Gotchas

Promises are powerful, but they have real constraints. This part is the honest accounting most tutorials skip.

#PostDescription
19Promise Limitations and PitfallsNo cancellation, no progress, eager execution, silently swallowed rejections, and mixing .then(null, fn) with .catch() incorrectly
20Memory and Performance ConsiderationsMicrotask queue pressure, long chains vs flat await, and avoiding memory leaks with settled promises

Part VII — Building the Polyfill

The payoff. By this point in the series, you have enough context to read the Promises/A+ specification and actually understand it. This part walks through implementing a fully compliant Promise from scratch, step by step.

#PostDescription
21The Promises/A+ Specification — A Deep ReadWhat the spec covers, the resolution procedure [[Resolve]](promise, x) line by line, and the microtask requirement
22Scaffolding the Polyfill — State and ExecutorRepresenting state with closures, running the executor safely, and implementing single-fire resolve/reject
23Implementing .then()Creating the chained promise, queueing pending handlers, and scheduling with queueMicrotask
24Implementing the Resolution ProcedureThenable detection, adopting the state of returned promises, and guarding against circular resolution
25Adding .catch(), .finally(), and Static MethodsDeriving instance methods from .then() and implementing all four static combinators
26Testing and Validating the PolyfillRunning the official Promises/A+ compliance suite, fixing edge cases, and comparing against native Promise

Part VIII — Interview Corner

These posts are written specifically for interview preparation. Each one is self-contained and assumes you’ve worked through the series — they won’t just give you answers to memorise, they’ll give you the understanding to derive those answers yourself.

#PostDescription
27Predict the Output — Promise Execution OrderA curated set of tricky snippets involving microtasks, chaining, and async/await — with deep explanations of every output
28The Most Common Promise Interview QuestionsThe questions that come up repeatedly, answered properly — states, what .then() returns, difference between all and allSettled, and more
29Implement These in an Interview — Promise UtilitiesWalking through live implementations of promisify, retry, a concurrency limiter, and Promise.all from scratch
30async/await vs Promises — Interview EditionHow to articulate the relationship clearly, what interviewers are actually testing, and the common misconceptions to avoid

Who This Is For

  • JavaScript developers who use Promises daily but want to understand what’s actually happening under the hood
  • Interview preppers — Promises are one of the most commonly misunderstood topics in JS interviews, and Part VIII is written specifically for you
  • Frontend and Node.js engineers dealing with complex async flows in production
  • Curious minds who just want to know how something really works

No prior knowledge of async internals is assumed. If you know what a function is, you can start at Post 01.


A Note on the Polyfill

The polyfill we build in Part VII is written for learning, not production. The goal is to make every line of the spec click into place. By the end, you will understand native Promises well enough that reading the V8 source code feels approachable.


Posts will be linked as they are published. The series is written in order — each post assumes you’ve read the ones before it in the same part.

Honey Sharma

Software engineer focused on web engineering, TypeScript, and distributed systems.