A Value That Isn't Ready Yet
Callbacks get hard to read when one step depends on another. Do this, then with the result do that, then something else. Each step goes inside the callback of the step before it, and the code moves further to the right with every step. People call this callback hell.
A Promise fixes this. A promise is an object that stands for a value that is not ready yet.
A promise starts as pending. Later it becomes resolved (it worked, and has a value) or rejected (it failed, and has an error). This happens only once. You use .then to say what should run when the promise is resolved:
const wait = ms =>
new Promise(resolve => setTimeout(resolve, ms));
wait(100).then(() => console.log("done waiting"));
Output:
done waiting
The wait function builds a promise around setTimeout. new Promise gives you a function called resolve. You call it when the work is done, and here the timer calls it after ms milliseconds. In real code you rarely build promises yourself. Tools for web requests, files and databases already give you promises. You mostly use them with .then.
.then returns a new promise. So you can put the next .then straight after it, and the steps form a flat chain that reads from top to bottom:
const wait = ms =>
new Promise(resolve => setTimeout(resolve, ms));
wait(100)
.then(() => {
console.log("cooking...");
return wait(100);
})
.then(() => console.log("served"));
Output:
cooking...
served
The first .then returns the promise from wait(100). The second .then waits until that promise is resolved too, so served prints only after the second wait is over.
To handle a failure, put .catch at the end of the chain. If any step throws an error, the next steps are skipped and .catch runs:
const wait = ms =>
new Promise(resolve => setTimeout(resolve, ms));
wait(100)
.then(() => {
throw new Error("oven is broken");
})
.then(() => console.log("served"))
.catch(err => console.log("problem:", err.message));
Output:
problem: oven is broken
One .catch covers the whole chain. With plain callbacks, every step needs its own error check.
The next lesson shows async and await, a shorter way to write the same steps. You will use them more often. But they work with promises underneath, so it helps to understand .then first.
In the exercise, chain two .then steps to cook and serve an order.