JS Sketchbooksee JavaScript think ✏️
← back to phase 6

6.4 — Promises

Last lesson's pain, prescribed a cure. Instead of you handing your next step INTO the async function (a callback), the function hands YOU something back: a promise — a receipt for work in progress. Order a burger, get a receipt immediately. The receipt isn't the burger — it's a live object that will flip when the kitchen finishes, and you can attach plans to it: "when ready, do this; if it fails, do that."

Three states, one flip: that's the whole shape of a promise.

Flat chains and a single shared error drain follow from it — by the end of this lesson the pyramid of doom is a straight line, and you'll have built a promise with your own hands.

watch it happen
const order = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("burger #42");
  }, 60);
});

console.log("receipt in hand");

order
  .then((food) => {
    console.log("eating " + food);
    return food + " + fries";
  })
  .then((meal) => {
    console.log("upgraded: " + meal);
  })
  .catch((err) => {
    console.log("refund: " + err.message);
  });

new Promise((resolve, reject) => { …start the work… }) — the executor function runs IMMEDIATELY and starts the async work (here, a timer). What you get back, instantly, is the receipt: a promise in state PENDING. Two levers are handed to the executor: resolve(value) to flip it to success, reject(error) to flip it to failure.

the promise — a receiptPENDINGplans attached to the receiptnew Promise((resolve, reject) => {…}) starts the work immediately andhands you back a promise — a receipt for work in progress, state: pending(console: nothing yet)
under the hood

The deeper story, with the real names for things — this part is what turns “I saw it” into “I can explain it.”

A promise is a plain object with internal state (pending / fulfilled / rejected) plus lists of reactions to run on settle.

Precision that impresses: .then doesn't "wait" — it registers and immediately returns the next promise.

Attach a .then to an already-settled promise and it still runs (soon, not instantly — the exact "when" is next lesson's microtask story).

You'll consume promises far more often than construct them. fetch (6.7) returns one; every Playwright action returns one. Your test code will be promise-chains written in 6.6's async/await syntax. Building one by hand today (the exercise) is like taking apart a lock: afterward, every key makes sense.

Naming note for the wild: people say "resolved" loosely to mean fulfilled; strictly, settled = no longer pending (either outcome), fulfilled = success, rejected = failure.

Use the strict words in interviews; understand the loose ones in blog posts.

your turn

⌨️ build the receipt machine

Make your own promise from scratch — then transform its value through a FLAT two-link chain (no nesting anywhere).

requirements:

  • A function delayValue(ms, value) that returns a new Promise which resolves with value after ms milliseconds (setTimeout inside the executor).
  • Call delayValue(50, 10) and attach a chain: the first .then doubles the value and RETURNS it; the second .then adds 1 and prints the result.
  • Output must be 21 — and your chain must be flat: two .then links in a row, no callback inside a callback.

when you press RUN, the console must show exactly:

21

✏️ Quick check 1

A new Promise whose executor’s resolve fires in 5 seconds — what STATE is it in right after creation? Type it.

✏️ Quick check 2

Type exactly what this prints:

Promise.resolve(5)
  .then((n) => {
    return n + 1;
  })
  .then((n) => {
    console.log(n * 10);
  });

✏️ Quick check 3

The promise a chain STARTS from rejects. The chain has three .then links after it and one final .catch. How many of the .then links run? Type the number.

teach it back

🗣️ Now teach it back

Explain promises to a friend using the receipt picture: the three states and the one-flip rule, what .then really does (and returns!), how chains stay flat, and where errors go.

Write it as if your friend is sitting next to you. Saved to your journal — future-you will use these notes to teach others.

a few sentences, minimum — you’ve got this
to remember
A promise = a receipt: pending → (one flip, once) → fulfilled(value) or rejected(error).
.then registers a plan AND returns a new promise fed by your return value → flat chains that read top-to-bottom. (Returned promises are awaited by the chain.)
Rejections skip every .then into ONE shared .catch; .finally runs either way. Build them rarely, consume them constantly (fetch, Playwright).