Promises
Promises are introduced in ES6 to simplify asynchronous programming. Otherwise, you may end up in callback hell: callback inside callback inside callback.
A promise is an object that represents the result of an asynchronous computation (Flanagan). It can be in one of these states (MDN):
- pending — the initial state ("loading")
- fulfilled — the operation was completed successfully
- rejected — the operation failed
There is no way to synchronously get the value of a promise; you can only ask them to call a callback when it is fulfilled or rejected.
Creating a promise
Use the new Promise()
constructor. It accepts a single callback(resolve, reject)
function argument.
- Call
resolve(value)
to fulfill your promise (with the data) - Call
reject(error)
to reject your promise (with the reason/error)
For example, to "convert" Node's callback-based fs.readFile
into a promise:
const fs = require('fs');
function promisedReadFile(filePath) {
return new Promise((resolve, reject) => {
fs.readFile('/Users/joe/test.txt', 'utf8', (err, data) => {
if (err) {
reject(err);
return;
}
resolve(data);
});
});
}
// We'll come back to `.then()` and `.catch()` later
promisedReadFile('./path/to/file.txt')
.then((data) => {
console.log('Read file content', data);
})
.data((err) => {
console.error('An error happened', err);
});
The promise chain
When you have a promise object, you can call onto them:
promise.then((data) => {...})
— to do something when the promise has fulfilled. Inside the callback, you can return a value or another promise on which you can call.then(...)
, creating a promise chain.promise.catch((err) => {...})
— to do something when the promise has rejectedpromise.finally(fn)
— to do something after the promise has fulfilled or rejected
A sample of a promise chain will look like this:
The Promise
class
Promise utilities
Promise.all(...promises)
Creates a Promise
object that fulfills when all promises
have fulfilled (the resolved value is an array). It rejects as soon as one of the promises
rejects.
// Use this to run promises concurrently
Promise
.all([fetch(urlA), fetch(urlB)])
.then([resA, resB] => {...});
Promise.allSettled(...promises)
Creates a Promise
object that fulfills when all promises
have fulilled or rejected.
Promise.any(...promises)
Creates a Promise
object that fulfills as soon as one of the promises
fulfills. It rejects if all of the promises
rejects.
Promise.race(...promises)
Creates a Promise
object that fulfills as soon as one of the promises
fulfills or rejects.
Creating a Promise
object
Promise.resolve(value)
Creates a new Promise
object that resolves with the given value.
Promise.resolve(1234);
Promise.reject(reason)
Creates a new Promise
object that rejects with the given reason.
Promise.reject(new Error('Whoops'));
References
- JavaScript: The Definitive Guide, 7th Edition (David Flanagan) — Chapter 13. Asynchronous JavaScript
- Promise — https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise