DMarlon Studio

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.

JavaScript · Promises in DMarlon Studio: the example's code and its output in the terminal

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.
  • resolve delivers the value and reject the error.
  • Whatever a then returns reaches the next one; a returned promise is awaited.
  • A rejection jumps to the first catch; finally always 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.