JavaScript Promises all you need know
What are Promises exactly?
An Intro:
Promises are a strong API in JavaScript that facilitates us to do async operations and postponed computations easier. Simply, an unfinished operation is represented by a promise.
A promise, in simple terms, is a placeholder for a value that will be accessible later.
So, what’s the big deal?
As we know JavaScript is single threaded, two scripts cannot run simultaneously and must be executed rapid succession.
JavaScript is threaded in browsers alongside a lot of other things that varies from browser to browser. However, painting, changing styles, and managing user events are usually in the same queue as JavaScript (such as highlighting text and interacting with form controls).
One of these activities causes the others to be delayed.
A promise could be in one of three stages:
· Pending: Awaiting a response
· Promise kept: Success follows.
· Promises are broken when they are rejected.
Promise chaining in JavaScript
Sometimes you’ll want to run two or more asynchronous operations in a row, with the next operation starting with the output of the prior one. As an illustration:
To begin, create a new promise that resolving to the number 10 after three seconds:
let p = new Promise((resolve, reject) => {setTimeout(() => {
resolve(5);
}, 3 * 100);
});p.then((result) => {
console.log("Result One:", result);
return result * 2;
}).then((result) => {
console.log("Result Two:", result);
return result * 3;
});
Methods of Promises
Promise.all()
Promise.all() is a promise that receives an array of promises as input (an iterable).
The situation is then resolved when all the promises have been performed or one of them has been refused.
In Simple Words
The Promise.all() method accepts an iterable of promises and returns a single Promise that resolves to an array of the input promises’ results.
When all of the promises in the input iterable have resolved, or if the input iterable contains no promises, this returned promise will resolve. It rejects instantly if any of the input promises fail or non-promises fail, and it rejects with this first rejection message / error.
Let’s look at it in code:
Promise.all([Promise1, Promise2, Promise3]).then(result) => {console.log(result)}).catch(error => console.log(`Error in promises ${error}`))
We pass an array to Promise.all() as you can see. Promise.all() resolves and the output is consoled when all three promises are resolved. The part that interests me is how Promise returns the promise.All() returns resolved or rejected.
Another Example:
const promise_1 = Promise.resolve(5);const promise_2 = 50;const promise_3 = new Promise((resolve, reject) => {setTimeout(resolve, 200, ‘bar’);});Promise.all([promise_1, promise_2, promise_3]).then((values) => {console.log(values);});// expected output: Array [5, 50, “bar”]
Note: The setTimeout() method is used to mimic an asynchronous action.
The most fascinating point is that if at least one promise fails, all subsequent promises fail for the same reason (without waiting for following promises to settle).
Promise.allSettled()
Promise.allSettled() methods produces a promise that resolves once all of the specified promises have been fulfilled or rejected, together with an array of objects that explain each promise’s conclusion.
It’s commonly used when you have several asynchronous activities that don’t need to finish to succeed, or when you want to always know the outcome of each promise.
Example:
let promise_1 = Promise.resolve(400);let promise_2 = Promise.reject(“Rejected Promise”);let promise_3 = new Promise((resolve, reject) =>{setTimeout(() => resolve(500), 100)});let result = Promise.allSettled([promise_1, promise_2, promise_3 ]);result.then((value) => console.log(value));
Promise.any()
Promise.any() accepts a list of Promise objects as an argument. It produces a single promise that resolves with the value of the fulfilled promise as soon as any of the promises in the iterable fulfils.
If none of the promises in the iterable fulfil (all of the specified promises are rejected), the returning promise is rejected with an AggregateError, a new Error subclass that aggregates together separate errors.
Example:
const promise_1 = Promise.reject(0);const promise_2 = new Promise((resolve) => setTimeout(resolve, 50, ‘quick’));const promise_3 = new Promise((resolve) => setTimeout(resolve, 70, ‘slow’));const promises = [promise_1, promise_2, promise_3];Promise.any(promises).then((value) => console.log(value));// expected output: “quick”
Promise.race()
Promise.race() receives a list of promises as an iterable object and produces a new promise that fulfills or rejects as soon as one promise fulfils or rejects, with the value or reason from that promise.
Example:
const promise_1 = new Promise((resolve, reject) => {setTimeout(resolve, 100, ‘first’);});const promise_2 = new Promise((resolve, reject) => {setTimeout(resolve, 50, ‘second’);});Promise.race([promise_1, promise_2]).then((value) => {console.log(value);// Although both resolve, promise_2 is quicker.});// expected output: “second”
The race function returns a Promise that is resolved in the same method (and takes similar value) as the first promise in the iterable supplied as an input.
The promise returned will be indefinitely pending if the iterable passed is empty. Promise.race() will resolve with the first of these values discovered in the iterable if the iterable contains one or more non-promise values and/or an already settled promise.
Promise.finally()
A Promise is returned by the finally() method. The supplied callback function is run when the promise is resolved, that is, when it is either fulfilled or denied. Once the Promise has been dealt with, this allows code to be executed to determine if the promise was successfully fulfilled or denied.
In Simple words, whether the promise is fulfilled or refused, the finally() method is always called.
In other words, when the promise is resolved, the finally() function is called.
This avoids duplicating code in the then() and catch() handlers of the promise.
Example:
fetch(myRequest).then(function(response) {var contentType = response.headers.get(“content-type”);if(contentType && contentType.includes(“application/json”)) {return response.json();}throw new TypeError(“Oops, we haven’t got JSON!”);}).then(function(json) { /* process your JSON further */ }).catch(function(error) { console.error(error); /* this line can also throw, e.g. when console = {} */ }).finally(function() { isLoading = false; });
Promise.resolve()
A Promise is an object that reflects the successful or unsuccessful execution of a user task.
In JavaScript, a promise can be in one of three states: pending, fulfilled, or rejected.
The key benefit of utilising a Promise in JavaScript is that it allows you to bind callback functions to promises in case they are rejected or fulfilled, and it also allows you to conveniently manage the control flow of all asynchronous events or data that are coming up. A promise is either kept or broken, as the term implies. As a result, a promise is either fulfilled (kept) or rejected (broken).
var original = Promise.resolve(33);var cast = Promise.resolve(original);cast.then(function(value) {console.log(‘value: ‘ + value);});console.log(‘original === cast ? ‘ + (original === cast));
Because the then handlers are invoked asynchronously, the logs appear in reverse order.
Check out how it works.
Warning: Promise is not to be called. On a thenable that resolves to itself, use resolve().
Because it attempts to flatten an infinitely-nested promise, this leads to endless recursion.
Before we end…
Thank you for reading this far! Let’s connect. You can add me on Linkdin with comments.
That’s all for now. See you again with my next article soon. Until then, please take good care of yourself.