Reputation: 7849
I have a chain of promises
promisedStep1()
.then(promisedStep2)
.then(promisedStep3)
.then(promisedStep4)
.then(function (value4) {
// Do something with value4
})
.catch(function (error) {
// Handle any error from all above steps
});
And I need to know at which step I got an error.
If I add catch to each promised step
promisedStep1()
.catch(function(){
throw {code: 1}
})
.then(promisedStep2)
.catch(function(){
throw {code: 2}
})
.catch(function (error) {
console.log('error in ', error.code);
});
code
would be always 2, because it goes from first catch to second.
What are the techniques in handling such errors?
Edit
Found a way:
function promisedStep1Wrapper(){
return promisedStep1()
.catch(function(){
throw {code: 1};
});
}
function promisedStep2Wrapper(){
return promisedStep2()
.catch(function(){
throw {code: 2};
});
}
promisedStep1Wrapper()
.then(promisedStep2Wrapper)
.catch(function(err){
console.log(err.code);
});
Is this ok, or is there any better solution?
Upvotes: 1
Views: 535
Reputation: 665555
Is this ok?
Yes, totally.
or is there any better solution?
"Better" I don't know, but there are others for sure. One approach would be to only handle those errors you expect - the ones from the previous step, and rethrow everything else. Some libraries like Bluebird do have dedicated helper function for this definitely superior approach. It would basically look like this:
promisedStep1() // throws Step1Error
.catch(function(err) {
if (!(err instanceof Step1Error)) throw err;
throw {code: 1};
})
.then(promisedStep2) // throws Step2Error
.catch(function(err) {
if (!(err instanceof Step2Error)) throw err;
throw {code: 2};
})
.catch(function(error) {
if (!("code" in error)) throw error; // duck typing
console.log('error in ', error.code);
})
.catch(function(error) {
console.error("completely unexpected:", error);
});
Another approach is nesting and using the second then
callback for dedicated error handling - see When is .then(success, fail) considered an antipattern for promises? for the difference to .then().catch()
. Using this, your code would look like
promisedStep1()
.then(function(res) {
return promisedStep2(res)
.then(function(res) {
// do something
return res;
}, function(err) { // error in promisedStep2
throw {code: 2};
});
}, function(err) { // error in promisedStep1
throw {code: 1};
})
.catch(function(error) {
if ("code" in error)
console.log('error in ', error.code);
else
console.error("completely unexpected:", error); // from "do something"
});
This approach works well and allow fine-grained control over attaching which handlers where, cleanly separating success and error paths, but is a bit syntactically confusing.
Upvotes: 1