Promises
A promise is an object that promises a result in the future. While the action is in progress there is no result yet; when it ends, the promise is either fulfilled with a value or rejected with an error. All modern asynchronous work is built on promises: server requests, reading files, waiting.
then
To get a promise's result, pass a function to its then() method. It is called when the value appears:
const promise = Promise.resolve(42);
promise.then((value) => {
console.log(value); // 42
});Promise.resolve() creates an already fulfilled promise — a handy way to show then() without extra code.
Promise states
A promise has three states. From pending it moves to one of the two final ones and never changes again:
| State | Meaning |
|---|---|
| pending | No result yet |
| fulfilled | There is a value; the functions from then() are called |
| rejected | An error occurred; the functions from catch() are called |
Creating a promise
You create your own promise with new Promise(). You pass it a function that calls resolve when the result is ready:
const promise = new Promise((resolve) => {
setTimeout(() => {
resolve('Done');
}, 300);
});
promise.then((value) => {
console.log(value); // Done
});This promise is fulfilled after 300 ms. This is how old callback-based functions are wrapped in a promise.
Errors and catch
The second parameter, reject, rejects the promise with an error. The catch() method catches it:
const promise = new Promise((resolve, reject) => {
reject(new Error('The server is not responding'));
});
promise.catch((error) => {
console.log(error.message); // The server is not responding
});A rejected promise without catch() leaves an Uncaught (in promise) message in the console.
Chains
then() itself returns a new promise, so calls are lined up in a chain. Whatever one function returns, the next one receives:
Promise.resolve(2)
.then((value) => value * 10)
.then((value) => value + 1)
.then((value) => {
console.log(value); // 21
});A single catch() at the end of the chain catches an error from any of its links.
finally
The function in finally() runs in any case — on success and on error. It is the place for finishing actions, such as hiding a loading indicator:
Promise.reject(new Error('No connection'))
.catch((error) => console.log(error.message))
.finally(() => console.log('Loading finished'));
// No connection
// Loading finishedCommon mistake
Forgetting return inside then() when the function has curly braces. The next link of the chain then receives undefined:
Promise.resolve(5)
.then((value) => {
value * 2;
})
.then((result) => {
console.log(result); // undefined
});Write return value * 2, or use a short arrow without braces: (value) => value * 2.