How Can I Use Promises To Catch Errors When They Might Not Be Wrapped In A Promise?
Solution 1:
The reason your .catch
es are not working is that the errors are being thrown synchronously. The code execution never even executes that .catch() instruction to set up a catch handler because the error has already been thrown and the code execution has gone elsewhere. If you wrapped everything in an ordinary try-catch
, I think you'd see it catching the errors you're throwing.
Example:
let goodFun = function() {
return"I like bananas!";
};
//blows up!let badFun = function() {
throw"A general error blaahh!";
};
try {
Promise.all([goodFun(), badFun()])
.then(results =>console.log(results))
.catch(error =>console.error(error))
} catch (e) {
console.error("Wups, I caught an error. This wasn't supposed to happen.", e);
}
This is confusing for me, because according to the MDN documentation the array may contain a Promise, or a result from one (like a string, or a number).
The MDN documentation is absolutely correct, but if badFun()
throws an error, there's nothing that Promise.all
can do about it, because the the program flow will be going down the call stack looking for something to catch the error that was thrown.
If you're not sure whether some code is synchronous or promise-based (or if it will throw a synchronous error), you can use this to safely wrap it a promise:
functionexecuteSafe(action) {
returnPromise.resolve().then(action);
}
This will shield action() from any "boom" that takes place.
Example:
letexecuteSafe =
action => Promise.resolve().then(action);
letgoodFun =
() => "I like bananas!";
//blows up!letbadFun =
() => { throw"A general error blaahh!" };
Promise.all([goodFun, badFun].map(executeSafe))
.then(results =>console.log(results))
.catch(error =>console.error(error))
FYI, if you're using Bluebird, then it has a built-in method Promise.try
, that serves the same purpose as executeSafe
above: Promise.all([goodFun, badFun].map(Promise.try))
.
Here's your full example with the needed modifications:
letexecuteSafe =
action => Promise.resolve().then(action);
letgoodFun =
() => "I like bananas!";
//blows up!letbadFun =
() => {
throw"A general error blaahh!"
};
letasyncFun =
() => Promise.all([goodFun, badFun].map(executeSafe));
let executor = function() {
let numbsArray = [1, 2, 3];
returnPromise.all(numbsArray.map(num =>asyncFun()
.catch(error =>console.log(`I failed with ${error} and ${num}`))
));
}
executor();
And here it is with the .catch
outside of the executor
:
letexecuteSafe =
action => Promise.resolve().then(action);
letgoodFun =
() => "I like bananas!";
//blows up!letbadFun =
() => {
throw"A general error blaahh!"
};
letasyncFun =
() => Promise.all([goodFun, badFun].map(executeSafe));
let executor = function() {
let numbsArray = [1, 2, 3];
returnPromise.all(numbsArray.map(asyncFun));
}
executor().catch(error =>console.error("Miserably failed to catch anything.", error));
Post a Comment for "How Can I Use Promises To Catch Errors When They Might Not Be Wrapped In A Promise?"