Promise Then And Catch Clauses Not Working
Solution 1:
The problem here is that you are misunderstanding how Promise.all()
works. The way it works is that if all of the promises succeed, it resolves to an array of values. If any of them fail, it rejects with the first error that occurred.
What you seem to be expecting, that the successful ones are caught in the then
and the failed ones are caught in the catch
, is not possible. A promise either resolves once or it rejects once. It doesn't do both, and it won't do one or the other multiple times. Promise.all()
returns a single promise so it will either resolve or reject.
Third party promise libraries do have methods for "settling" an array of promises - basically waiting until they have all done their thing (succeeded or failed), and resolving to an array of the results. You can implement it like this:
// values is an array of promises and/or non-promise valuesfunctionallSettled(values) {
letsettle =
value => Promise.resolve(value)
.then(result => ({ state: "fulfilled", value: result }))
.catch(error => ({ state: "rejected", reason: error }));
returnPromise.all(values.map(settle));
}
// example usageallSettled(['hello', 'goodbye', Promise.resolve('good'), Promise.reject('bad')])
.then(results =>console.log(results));
Then you can use it like below.
On an unrelated note, I've also modified your approach so that you don't need the modified version of executeSave
that takes ...args
(I think that's a convoluted way to go about it). You can create functions that use the arguments before you pass them into _executeSafe_
:
letgoodFun = (fruit) => `I like ${fruit}`;
letbadFun = (fruit) => {
throw`${fruit} is spoiled!`;
};
letbadPromise = (fruit) => Promise.reject(`Promise failed with ${fruit}`);
letgoodPromise = (fruit) => Promise.resolve(`Promise succeeded with ${fruit}`);
letexecuteSafe = fun => Promise.resolve().then(fun);
functionallSettled(values) {
letsettle =
value => Promise.resolve(value)
.then(result => ({ state: "fulfilled", value: result }))
.catch(error => ({ state: "rejected", reason: error }));
returnPromise.all(values.map(settle));
}
letasyncFun =
(fruit) =>
allSettled([badFun, goodFun, badPromise, goodPromise]
.map(fun =>() =>fun(fruit))
.map(executeSafe)
);
asyncFun("orange").then(results =>console.log(results));
Additional side note - if you wanted to use the promisify
function from Jared Smith's answer, then you could change your asyncFun
function to this:
let asyncFun =
(fruit) =>
allSettled([badFun, goodFun, badPromise, goodPromise]
.map(promisify)
.map(fun => fun(fruit))
);
Solution 2:
So this works, catches fine. If the function passed to promisify
returns a promise, it just gets passed up the chain.
varfnThatThrows = s => { thrownewError(s) };
varidentity = x => x;
varpromisify = f => (...args) =>newPromise((res, rej) => {
try {
res(f(...args));
} catch (e) {
rej(e);
}
});
var rejected = promisify(fnThatThrows);
rejected("foo").then(_ =>console.log("shouldn't see")).catch(e =>console.log(e)); // logs errorvar succeded = promisify(identity);
succeeded("foo").then(val =>console.log(val)); // logs 'foo'
If the promise from the argument function is rejected, that gets passed along too:
varreturnsBadPromise = s => Promise.reject(newError(s));
promisify(returnsBadPromise)("foo").catch(e =>console.log(e)); // logs error
Post a Comment for "Promise Then And Catch Clauses Not Working"