Building A Promise From Scratch

Post 6 mentioned building a Promise is a separate skill from consuming one. This is that skill: the Promise constructor, resolve and reject, and wrapping old callback-based code in one.

July 11, 20263 min read14 / 22

Post 6 mentioned that building a Promise is a separate skill from consuming one, and set it aside for later. Later is now.

The Promise Constructor

new Promise(executor) builds one, and that executor function runs immediately, the instant the constructor is called, not later. It receives two arguments of its own: resolve and reject, functions used to decide how the Promise settles.

JavaScript ยท Live Editor
Loading editor...

Hit Run a few times. Whatever gets passed to resolve() becomes the value a .then() receives; whatever gets passed to reject() becomes what .catch() receives. That's the entire mechanic, the same resolve/reject split that decided the fulfilled/rejected branches back in post 6, just triggered by hand instead of by a network response.

The lifecycle of a Promise: pending while the task runs, then settling exactly once into either fulfilled or rejected, a state that never changes afterward. ExpandThe lifecycle of a Promise: pending while the task runs, then settling exactly once into either fulfilled or rejected, a state that never changes afterward.

Making It Actually Asynchronous

That version settles the instant it's created, which makes it a Promise in name only. Wrapping the decision in setTimeout is what makes it genuinely asynchronous, and swapping the plain string for a real Error object is worth doing too, exactly like throwing a real error a few posts back.

JavaScript ยท Live Editor
Loading editor...

Run it and '๐Ÿ”ฎ Flipping the coin...' prints immediately, then a real second passes before the outcome settles. One nuance worth knowing: calling resolve or reject a second time does nothing, a Promise settles once, the same rule from post 6, it just applies here too, to a Promise you built yourself instead of one fetch returned.

Promisifying: Wrapping Old Callback-Based Code

Most of the time, building a Promise from scratch means wrapping something older that only takes a callback, setTimeout itself included. That's called promisifying.

JavaScript ยท Live Editor
Loading editor...

No reject here at all, a timer can't actually fail, so there's nothing to reject with. wait() now behaves exactly like fetch, a function that returns a Promise instead of asking for a callback, which means it chains.

JavaScript ยท Live Editor
Loading editor...

That's the exact same four-timer example from the callback hell post, rebuilt flat. No pyramid, no nesting, one promisified function chained four times.

The Essentials

  1. new Promise((resolve, reject) => {...}) runs its executor function immediately, not later.
  2. resolve(value) fulfills the Promise; reject(reason) rejects it. Whichever fires first decides the outcome, calling the other afterward does nothing.
  3. Wrapping the resolve/reject call in something like setTimeout is what makes a built Promise genuinely asynchronous, instead of settling the instant it's created.
  4. Promisifying means writing a function that returns a Promise instead of accepting a callback, exactly what turns old callback-based code into something chainable.
  5. A promisified helper like wait() chains sequential delays flat, the same pyramid from post 5, gone.