27
loading...
This website collects cookies to deliver better user experience
then()
, catch()
and finally()
and how they can be chained together to form a promise chain. pending
state and eventually became either fulfilled
or rejected
when we called resolve()
or reject()
inside the executor function. Promise.resolve()
enables us to directly create a fulfilled
promise object with the value that we pass to it.// returns an already fulfilled promise
var promise = Promise.resolve( "fulfilled😇" );
console.log( promise );
// Promise { <state>: "fulfilled", <value>: "fulfilled😇" }
promise
directly attains the fulfilled
state without ever being in the pending
state. Promise.resolve()
comes in very handy when we want to quickly create a promise object without going through the whole constructor and executor function business. Just pass the value to Promise.resolve()
as an input and you get back a promise object.Promise.resolve()
, this function enables us to directly create a rejected
promise object rejected with the reason that we pass to it.// returns an already rejected promise
var promise = Promise.reject( "something went wrong🤦♂️" );
console.log( promise );
/*
Promise {
<state>: "rejected",
<reason>: "something went wrong🤦♂️"
}
Uncaught (in promise) something went wrong🤦♂️
*/
promise
directly attains the rejected
state without ever being in the pending
state.Promise.all()
. For convenience, we'll just use an array of promises as an input to Promise.all()
.Promise.all()
returns a new promise. This returned promise object gets fulfilled when all of the input promises fulfill. It gets rejected if any of the input promises gets rejected. This is what makes Promise.all()
suitable for managing multiple asynchronous operations that are dependent on each other.var promise1 = new Promise( (resolve, reject) => {
setTimeout(() => {
resolve( 1 );
}, 1000);
});
var promise2 = new Promise( (resolve, reject) => {
setTimeout(() => {
resolve( 2 );
}, 2000);
});
var returnedPromise = Promise.all([ promise1, promise2 ]);
// log returnedPromise before any of the promises settle
console.log( "Initially: ", returnedPromise );
// log returnedPromise after promise1 has settled
promise1.then( value => {
console.log( "After promise1 settles: ", returnedPromise );
});
// log returnedPromise after promise2 has settled.
promise2.then( value => {
console.log( "After promise2 settles: ", returnedPromise );
});
/*
Initially: Promise { <state>: "pending" }
After promise1 settles: Promise { <state>: "pending" }
After promise2 settles: Promise {
<state>: "fulfilled",
<value>: [ 1, 2 ]
}
*/
promise1
gets fulfilled after 1 second with a value of "1". But returnedPromise
from Promise.all()
doesn't get fulfilled yet. It waits for promise2
in its input array to be settled as well. When promise2
also gets fulfilled after 2 seconds with a value of "2", that is when returnedPromise
gets fulfilled. The value that returnedPromise
gets fulfilled with, is an array of the individual values that the input promises got fulfilled with, which in this case is [ 1, 2 ]
.var promise1 = new Promise( (resolve, reject) => {
setTimeout(() => {
resolve( 1 );
}, 1000);
});
var promise2 = new Promise( (resolve, reject) => {
setTimeout(() => {
reject( "something went wrong🤦♂️" );
}, 2000);
});
var promise3 = new Promise( (resolve, reject) => {
setTimeout(() => {
resolve( 3 );
}, 3000);
});
var returnedPromise = Promise.all([ promise1, promise2, promise3 ]);
// log returnedPromise before any of the promises settle.
console.log( "Initially: ", returnedPromise );
// log returnedPromise after promise1 has settled
promise1.then( value => {
console.log( "After promise1 settles: ", returnedPromise );
});
// log returnedPromise after promise2 settles.
promise2.catch( value => {
console.log( "After promise2 settles: ", returnedPromise );
});
// log returnedPromise after promise3 settles.
promise3.then( value => {
console.log( "After promise3 settles: ", returnedPromise );
});
/*
Initially: Promise { <state>: "pending" }
After promise1 settles: Promise { <state>: "pending" }
After promise2 settles: Promise {
<state>: "rejected",
<reason>: "something went wrong🤦♂️"
}
Uncaught (in promise) something went wrong🤦♂️
After promise3 settles: Promise {
<state>: "rejected",
<reason>: "something went wrong🤦♂️"
}
*/
promise1
gets fulfilled after 1 second. At this point, returnedPromise
stays in the pending
state as expected waiting for promise2
and promise3
to settle as well. But promise2
gets rejected. This causes returnedPromise
to be rejected as well with the same reason with which promise2
rejected. Promise.all()
doesn't wait for promise3
to settle. As soon as it encounters a rejection in one of its input promises, Promise.all()
will reject its returned promise which is why in promise-land, we say that Promise.all()
short-circuits when an input promise is rejected. Promise.all()
is passing an empty array as an input. In this case, Promise.all()
returns an already fulfilled promise with a blank array as the value.var returnedPromise = Promise.all( [] );
console.log( returnedPromise );
// Promise { <state>: "fulfilled", <value>: [] }
pending
state initially and was later( or asynchronously) settled. In the above example, returnedPromise
is already fulfilled
i.e. it's fulfilled synchronously. This is the only case when Promise.all()
synchronously returns a settled promise otherwise the returned promise is always settled asynchronously.Promise.all()
and it picks up where Promise.all()
left off. Promise.allSettled()
will actually wait for the completion of all asynchronous operations meaning it will return a promise that will be settled only when each and every input promise has settled. Even if there is a rejection in one of the input promises, the returned promise will still wait for the rest of the them to be settled before finally being settled itself. This is what makes Promise.allSettled()
suitable for managing multiple asynchronous operations that are not dependent on each other. Promise.allSettled()
also takes an interable or an array as an input and returns a new promise.var promise1 = new Promise( (resolve, reject) => {
setTimeout(() => {
resolve( 1 );
}, 1000);
});
var promise2 = new Promise( (resolve, reject) => {
setTimeout(() => {
reject( "something went wrong🤦♂️" );
}, 2000);
});
var promise3 = new Promise( (resolve, reject) => {
setTimeout(() => {
resolve( 3 );
}, 3000);
});
var returnedPromise = Promise.allSettled([ promise1, promise2, promise3 ]);
// log returnedPromise before any of the promises settle.
console.log( "Initially: ", returnedPromise );
// log returnedPromise after promise1 has settled
promise1.then( value => {
console.log( "After promise1 settles: ", returnedPromise );
});
// log returnedPromise after promise2 settles.
promise2.catch( value => {
console.log( "After promise2 settles: ", returnedPromise );
});
// log returnedPromise after promise3 settles.
promise3.then( value => {
console.log( "After promise3 settles: ", returnedPromise );
});
/*
Initially: Promise { <state>: "pending" }
After promise1 settles: Promise { <state>: "pending" }
After promise2 settles: Promise { <state>: "pending" }
After promise3 settles: Promise {
<state>: "fulfilled",
<value>: [
{ "status": "fulfilled", "value": 1 },
{ "status": "rejected", "reason": "something went wrong🤦♂️" },
{ "status": "fulfilled", "value": 3 }
]
}
*/
returnedPromise
did not reject when promise2
rejected. Instead it waited till promise3
had settled. After all three promises settled, returnedPromise
got fulfilled. Also note that the value with which returnedPromise
is fulfilled is different than in the case of Promise.all()
. Here, the fulfilled value is not an array of simple values with which the input promises were fulfilled. It is instead an array of objects that represent the state of each of the input promises in the same order. If the input promise was fulfilled, the object contains status
and value
properties and if the input promise was rejected, it contains status
and the rejection reason
.Promise.allSettled()
, the returned promise will always be fulfilled. Even if all the input promises get rejected, the returned promise will still get fulfilled with an array of objects representing each rejected promise. Promise.allSettled()
, the behavior is similar to Promise.all()
i.e. it returns (synchronously) an already fulfilled promise with value as a blank array. In all other cases, the returned promise will be in the pending state initially and will be settled asynchronously.Promise.race()
will not wait for the other promises to be settled. As soon as the first input promise gets settled, the returned promise from Promise.race()
will be either fulfilled with the same value or rejected with the same reason as the first settled input promise.Promise.race()
also takes an interable or an array as an input and returns a new promise.var promise1 = Promise.resolve( 1 );
var promise2 = new Promise( (resolve, reject) => {
setTimeout(() => {
resolve( 2 );
}, 1000);
});
var returnedPromise = Promise.race([ promise1, promise2 ]);
// after promise1 gets settled
promise1.then( value => {
console.log( "After promise1 settles: ", returnedPromise );
});
/*
After promise1 settles:
Promise { <state>: "fulfilled", <value>: 1 }
*/
promise1
is already resolved, Promise.race()
does not wait for the completion of promise2
and returnedPromise
gets fulfilled with the same value as promise1
. Promise.resolve()
with Promise.reject()
in the above example, then promise1
will get rejected but will still be the first input promise to settle. So returnedPromise
will get rejected with the same value as promise1
.Promise.race()
, the returned promise will stay in the pending
state forever since there is no input promise that'll settle first, and in turn settle the returned promise.Note: Promise.any()
is in the PROPOSAL stage and still not fully supported by browsers and platforms so I am not going to go into a lot of detail about it and will update this article when its properly supported at some point in the future. But I have included this just so you know that something like this is in the works and should be available soon.
Promise.race()
, the only difference being that while Promise.race()
waits for the first input promise to be settled, Promise.any()
waits for the first input promise to be fulfilled
. Once an input promise is fulfilled, Promise.any()
will not wait for other promises to fulfill. Promise.race()
, Promise.any()
will ignore any input promises that reject until the first input promise fulfills. If no input promises fulfill or if all promises reject, Promise.any()
will throw an AggregateError
( a subclass of Error
) which will group together all individual errors.Promise.all()
, Promise.allSettled()
and Promise.race()
(also Promise.any()
whenever it becomes available in the future) are referred to as Promise Combinators because they combine multiple promises and flatten them into a single promise that these functions return....
Promise.all([ "foo", promise, 2 ]);
...
var returnedPromise1 = Promise.all([ "foo", Promise.resolve(1), 2 ]);
returnedPromise1.then( console.log );
// [ "foo", 1, 2 ]
var returnedPromise2 = Promise.allSettled([ "foo", Promise.resolve(1), 2 ]);
returnedPromise2.then( console.log );
/*
[
{ "status": "fulfilled", "value": "foo" },
{ "status": "fulfilled", "value": 1 },
{ "status": "fulfilled", "value": 2 }
]
*/
var returnedPromise3 = Promise.race([ "foo", Promise.resolve(1), 2 ]);
returnedPromise3.then( console.log );
// "foo"
Promise.resolve()
, the behaviour will remain the same.var returnedPromise1 = Promise.all([
Promise.resolve( "foo" ),
Promise.resolve( 1 ),
Promise.resolve( 2 )
]);
returnedPromise1.then( console.log );
// [ "foo", 1, 2 ]
var returnedPromise2 = Promise.allSettled([
Promise.resolve( "foo" ),
Promise.resolve( 1 ),
Promise.resolve( 2 )
]);
returnedPromise2.then( console.log );
/*
[
{ "status": "fulfilled", "value": "foo" },
{ "status": "fulfilled", "value": 1 },
{ "status": "fulfilled", "value": 2 }
]
*/
var returnedPromise3 = Promise.race([
Promise.resolve( "foo" ),
Promise.resolve( 1 ),
Promise.resolve( 2 )
]);
returnedPromise3.then( console.log );
// "foo"