Understanding the behavior of catch in Immediately Settled Promises
Ever wondered about the order of execution for immediately resolved or rejected promises, does the order even matter ? Let's find out.
Let's take an example first and see the execution here:
const inputs = [Promise.reject(1), Promise.resolve(2)]
Promise.race(inputs)
.then((val)=>console.log("val",val))
.catch((err)=>console.log("err:",err)) //output: err: 1
as you can see in the above example err: 1 gets logged as output
Let's write our custom Implementation of Promise.race so that we get an understanding of how the input array in the above example is getting processed internally:
function customPromiseRace(iterable) {
return new Promise((resolve, reject) => {
if (iterable.length === 0) {
return;
}
iterable.forEach((item) => {
Promise.resolve(item)
.then((value) => {
resolve(value);
})
.catch((err) => reject(err));
});
});
}
const inputs = [Promise.reject(1), Promise.resolve(2)];
customPromiseRace(inputs)
.then((val) => console.log("val:", val))
.catch((err) => console.log("err:", err)); //output: ?
what do you think? what should be the output here? As you have seen in the first example you must be thinking that output should be the same that is err: 1.
But surprise... surprise.... output here is val: 2 . By now you must be thinking about what exactly has happened here but my friend that's where the javascript gets interesting.
When I first faced this I kept wondering why this was happening, I tried digging into it and learned something new and interesting while looking for answers to my dilema.
领英推荐
Here comes the reason behind such behavior:
In cases like the above example when the input array contains both immediately resolved and rejected promises (e.g. `[Promise.reject(1), Promise.resolve(2)]`).
`.catch()` is scheduled, and does not run immediately after `.then()`. For immediately settled promises, `then()` run before any `.catch()`, hence the overall Promise is fulfilled with 2 instead of rejected with 1.
So, now the question is how to handle this edge case of immediately settled promises. We are going to make a little adjustment to our customPromiseRace function:
Note: The rejected promises also called `.then()` and the second parameter of `.then()` is the callback to handle rejected promises.
Here we are leveraging `.then()` it takes up to two arguments: callback functions for the fulfilled and rejected cases of the Promise
function customPromise(iterable) {
return new Promise((resolve, reject) => {
if (iterable.length === 0) {
return;
}
iterable.forEach((item) => {
Promise.resolve(item)
.then((val)=>resolve(val), (err)=>reject(err))
});
});
}
const inputs = [Promise.reject(1), Promise.resolve(2)];
customPromiseRace(inputs)
.then((val) => console.log("val:", val))
.catch((err) => console.log("err:", err)); //output: err: 1
Building Kosmc ??
11 个月If we change the above approach using async await then it will work fine.
Building Kosmc ??
11 个月But surprise... surprise.... output here is val: 1 . -> Change the answer to val:2 ??