A simple metaphor I've heard used before is that a Promise
in JavaScript is like ordering a cheeseburger at a fast food restaurant. When you pay for the cheeseburger, they give you a receipt with an order number on it. That receipt represents a placeholder for your future cheeseburger. No matter how hungry you are, you have no control on how long it will take to get your cheeseburger, so usually you end up doing something else in the meantime. Eventually, they call your number and you trade your receipt for your actual cheeseburger.
So how does this translate technically?
A Promise
is an asynchronous method that may eventually return something. These are asynchronous functions that give you the ability to return or chain synchronous functions that will only be invoked until the Promise returns a success response first.
In layman's terms, this function returns a 'promise' to supply a value at some point in the future, if ever.
Syntax:
new Promise( function(resolve, reject) { ... } );
States
A Promise can be in a pending, fulfilled, or rejected state.
A pending state is its initial state, not 'fulfilled' or 'rejected'. A fulfilled state means that the operation completed successfully. A rejected state means the operation failed, and hopefully returns a meaningful reason.
Promise Prototype Methods
A Promise prototype has two methods: then and catch.
then
The 'then' method is the most commonly used method in a Promise. This method is only invoked when a promise has been fulfilled.
Syntax:
Promise.prototype.then(onFulfilled, onRejected)
catch
The 'catch' method allows you to handle errors on rejected promises.
Syntax:
Promise.prototype.catch(onRejected)
A Very Simple Example
Assume you want to fire a function after a callback resolved after four seconds. Easy! We would go about this something like:
const logText = (shouldLog) => {
if (shouldLog) {
console.log('I fired immediately!');
}
};
const theCallback = () => {
setTimeout(function() {
return true;
}, 4000);
};
logText(theCallback); // I fired immediately!
This actually fired immediately. It didn't wait the four seconds specified in the timeout. So how do we fix this? Use a Promise!
const logText = (shouldLog) => {
if (shouldLog) {
console.log('I fired after four seconds!');
}
}
const theCallback = () => {
return new Promise((resolve) => {
setTimeout(function() {
resolve(true);
}, 4000)
});
}
theCallback()
.then(logText); // I fired after four seconds!
forEach Promise
If you want to do something after many promises resolve, you want to use Promise.all(iterable)
. This method resolves when all promises within it resolve, or no promises are found.
const promises = [];
array.forEach((item) => {
promises.push(asyncFunc(item))
})
Promise.all(promises)
.then(() => {
console.log('All items processed!');
});