问题
I'm wondering if there a way in Bluebird promises to .catch
a thrown error and then process some specific actions without branching (nested promise).
Say I have
doSomethingAsync()
.then(function (result) {
if (!result)
throw new CustomError('Blah Blah');
if (result == 0)
throw new CustomError2('Blah Blah Blah');
return result;
})
.then(function (result) {
console.log('Success, great!');
})
.catch(CustomError, function (error) {
// Oh CustomError!
return saveSomethingAsync();
})
.then(function (saved) {
// Should only be executed if an CustomError has been thrown
console.log("Let's try again");
return doSomethingAsync();
})
.catch(CustomError2, function (error) {
// Oh CustomError2!
})
.delay(15000) // Don't try again now !
.then(function () {
// Should only be executed if an CustomError2 has been thrown
console.log("Let's try again after some long delay");
return doSomethingAsync();
})
.catch(function (error) {
// Should catch all random errors of the chain
})
When I execute this code, I get several behaviours:
- If no error throws, I get "Success, great!" and it start again with "Let's try again after some long delay"
- If CustomError throws, I get "Let's try again"
- If CustomError2 throws, I get "Let's try again after some long delay"
I can't figure out what's happening with this flow. Should be great to write something like this instead of nesting the errors' specific code in new promise chains.
回答1:
.catch
a thrown error and then process some specific actions without branching
No. Because that is branching. Nesting is totally natural here. You could even think of this using the synchronous-try-catch
metaphor and it would be the same.
I can't figure out what's happening with this flow.
- If no error is thrown, I get "Success, great!" and it start again with "Let's try again after some long delay"
Hm, that's odd, because the "Let's try again" (without delay) is chained before that. You should eventually get both logs. Your chain is processed sequentially:
doSomethingAsync() // returns a result
then return result // first callback: continues with it
then console.log('Success, great!') // next callback: logs something
catch // is ignored because no rejection
then console.log("Let's try again"); // next callback: logs something
return doSomethingAsync(); // and returns a result
catch // that result, not being a rejection, is ignored here
delay // fulfillment is delayed
then console.log("Let's try again after some long delay"); // next callback again logs
return doSomethingAsync(); // and returns a result
catch // is ignored again
- If a CustomError is thrown, I get "Let's try again"
Yes, because saveSomethingAsync();
, the result of the previous promise, is fulfilled, so the next .then()
callback in the chain executes.
- If a CustomError2 is thrown, I get "Let's try again after some long delay"
Yes, because the error bubbled all the way down to .catch(CustomError2, …)
where it was eventually handled. On its way, no callbacks were executed. After the error was handled, the promise is fulfilled, and the next .then()
in the chain calls its callback.
I think what you really want here is
doSomethingAsync()
.then(function(result) {
if (!result)
// CustomError('Blah Blah');
// Oh CustomError!
return saveSomethingAsync();
.then(function(saved) {
console.log("Let's try again");
return doSomethingAsync();
});
else if (result == 0)
// CustomError2('Blah Blah Blah');
// Oh CustomError2!
return Promise.delay(15000) // Don't try again now !
.then(function() {
console.log("Let's try again after some long delay");
return doSomethingAsync();
})
else
console.log('Success, great!');
// return undefined implied
}).catch(function (error) {
// does catch all random errors of the chain
// thrown by any of the doSomethingAsync() or of the saveSomethingAsync
})
来源:https://stackoverflow.com/questions/29387939/bluebird-promises-and-catch-branching