Home › Learn › JavaScript › Async, errors, and classes

Promises

Lesson 36 of 40. Values that arrive later, and what to do when they do.

A promise represents a value that is not ready yet: a network response, a timer, a file. new Promise((resolve, reject) => ...) creates one; call resolve(value) when the value is ready or reject(error) on failure. .then(fn) registers what to do with the value and returns a new promise, so .then calls chain; .catch(fn) handles a rejection anywhere in the chain.

setTimeout(fn, ms) runs fn after a delay, and wrapping it in a promise gives a reusable delay(ms). Promise.all([p1, p2]) waits for several promises and resolves with an array of their values.

const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
delay(100).then(() => console.log("100 ms later"));

Promise.all([Promise.resolve(1), Promise.resolve(2)]).then((values) => console.log(values));   // [1, 2]

Your task

Write delay(ms) returning a promise that resolves after ms milliseconds with no value, and failAfter(ms) returning a promise that rejects after the delay with an Error whose message is "timed out". Then write fetchStock(name) returning a promise that resolves after 5 milliseconds with the stock count of that product from the STOCK table in the starter, or rejects with an Error whose message is unknown product: <name> when the table has no such product. Real code would ask a server; the delay stands in for the network.

Part of the final project. fetchStock looks up how many of a product are in stock, asynchronously, like a server call. It is saved in this browser and loaded into Project: checkout when you get there.

Hint 1

return new Promise((resolve) => setTimeout(resolve, ms));

Hint 2

failAfter: new Promise((resolve, reject) => setTimeout(() => reject(new Error("timed out")), ms)). fetchStock can reuse delay: return delay(5).then(() => { if (!(name in STOCK)) throw new Error("unknown product: " + name); return STOCK[name]; }); a throw inside then rejects the chain.

Show the solution
const STOCK = { keyboard: 12, cable: 140, monitor: 4, lamp: 8 };

function delay(ms) {
  return new Promise((resolve) => setTimeout(resolve, ms));
}

function failAfter(ms) {
  return new Promise((resolve, reject) => setTimeout(() => reject(new Error("timed out")), ms));
}

function fetchStock(name) {
  return delay(5).then(() => {
    if (!(name in STOCK)) throw new Error("unknown product: " + name);
    return STOCK[name];
  });
}

    Runs in an isolated web worker in this tab; nothing is sent anywhere.