Lesson 11 · 11 of 20
Promises · JavaScript
Learn how JavaScript promises work: resolve and reject, then chains, catch for errors and finally for clean-up.

A promise stands for a result that does not exist yet: it starts pending and ends up fulfilled (with a value) or rejected (with an error). checkStock builds one with new Promise, which receives two functions: it calls resolve when it has the data and reject when something goes wrong. The 50 ms setTimeout mimics waiting for a warehouse or a server.
Look at the order of the output: line 2 appears before line 3, even though it sits at the end of the program. JavaScript does not stop to wait for the promise; it keeps running the code and, when the answer arrives, it runs the functions registered with `then`.
Every then returns a new promise, so you can chain them: whatever one then returns (here, info.units * 899) is what the next one receives. If it returns another promise, like checkStock("mouse"), the chain waits for it to settle.
When a promise is rejected, the chain skips every then until the first `catch`: that is why This line is skipped never appears. `finally` runs at the end no matter what, which makes it the place to close a connection or hide a loading spinner. In the next lesson you will see async/await, which lets you write the same thing as sequential code.
Code · main.js
const stock = { laptop: 3, mouse: 0 };// A promise stands for a result that arrives later.function checkStock(product) { return new Promise((resolve, reject) => { setTimeout(() => { if (!(product in stock)) reject(new Error(`Unknown product: ${product}`)); else if (stock[product] === 0) reject(new Error(`${product} is out of stock`)); else resolve({ product, units: stock[product] }); }, 50); // pretend the warehouse takes 50 ms to answer });}console.log("1. Asking the warehouse...");checkStock("laptop") .then((info) => { console.log(`3. ${info.units} units of ${info.product}`); return info.units * 899; // the next then receives this value }) .then((value) => { console.log(`4. Stock value: ${value} EUR`); return checkStock("mouse"); // returning a promise: the chain waits for it }) .then(() => console.log("This line is skipped")) .catch((err) => console.log("5. Error:", err.message)) .finally(() => console.log("6. Request closed"));console.log("2. This line runs before the answer arrives");Output · node main.js
1. Asking the warehouse... 2. This line runs before the answer arrives 3. 3 units of laptop 4. Stock value: 2697 EUR 5. Error: mouse is out of stock 6. Request closed
Key points
- A promise is pending, fulfilled or rejected.
resolvedelivers the value andrejectthe error.- Whatever a
thenreturns reaches the next one; a returned promise is awaited. - A rejection jumps to the first
catch;finallyalways runs.
Exercise
Replace checkStock("laptop") with checkStock("tablet"), a product that does not exist, and see which steps are skipped. Then add a catch halfway that returns 0 so the chain carries on.