Reputation: 23705
I have 2 callback that both call API and return Promise
. They should go sequentially. Let's name them verifyThing
and updateThing
.
So without error handling it would be as easy as
verifyThing()
.then((id) => updateThing(id))
But now error handling comes. Suppose I need to display different error message once verifyThing
fails or updateThing
. Also obviously I don't need to call updateThing
if verifyThing
fails.
So far I've tried with custom Error:
class VerifyError extends Error {};
verifyThing()
.catch(e => {
message("cannot verify");
throw new VerifyError();
})
.then((id) => updateThing(id))
.catch(e => {
if (e instanceof VerifyError) return;
message("cannot update");
})
Unfortunately custom Error check does not work with Babel 6.26 we use. As a dirty patch I can throw magic string instead of Error subclass, but ESLint rules are for a reason, right?
So finally I have got working variant. But I believe it has worse readability(because of nesting):
verifyThing()
.catch(e => {
message("cannot verify");
throw e;
})
.then((id) =>
updateThing(id)
.catch(e => {
message("cannot update");
})
)
Is there any other way to handle all the logic in the same chain?
Upvotes: 3
Views: 56
Reputation: 350365
If async/await
is an option, then:
async function() {
let id;
try {
id = await verifyThing();
await updateThing(id);
} catch(e) {
message(id === undefined ? "cannot verify" : "cannot update");
throw e;
}
}
This assumes that when verifyThing()
fulfills, it will resolve with a defined value.
Upvotes: 2
Reputation: 51896
It seems like the actual behavior you want can be achieved by reordering your last example:
verifyThing().then(id =>
updateThing(id).catch(e => {
message("cannot update");
})
).catch(e => {
message("cannot verify");
})
The outer catch()
will only catch errors from verifyThing()
since errors from updateThing(id)
have been handled by the inner catch()
. In addition, you're always left with a resolved promise instead of a rejected one, which is appropriate since both types of errors have been handled already.
To avoid the appearance that error handling is not close to the source, move the inner portion to a helper function:
function tryUpdateThing (id) {
return updateThing(id).catch(e => {
message("cannot update");
});
}
verifyThing().then(
tryUpdateThing
).catch(e => {
message("cannot verify");
});
Whether or not this is acceptably readable, I'll leave up to you to decide.
Upvotes: 2