I've inherited a codebase at work that contains a dozen or so examples of the following pattern:
var promise = null;
try {
promise = backendService.getResults(input);
}
catch (exception) {
console.err(exception);
}
if (promise !== null) {
promise.then(function (response) {
// do stuff
})
.catch(function (error) {
console.err(error);
});
}
Where backendService
is an Angular service that in turn calls a REST service through $http
.
So here's my question: is that try/catch really necessary? Will there ever be any scenario where a particular error/exception is thrown that the promise's .catch
fails to catch?
This has been the subject of a bit of debate on the team all morning, and the only resolution we've come up with is that we don't think it's necessary, but (a) changing it breaks the tests that were written alongside it (which would also need to be changed), and (b) well... it's defensive coding, right? It's not a Bad Thing.
The merits of actually bothering to refactor it into oblivion when there are more important things to do aren't what I'm asking about, though. I just want to know if it's a reasonable pattern when promises are being passed around like this (in AngularJS specifically, if that makes a difference), or just paranoia.
Do promises in AngularJS catch every exception/error?
No. Only exceptions that are thrown from inside then
/catch
callbacks are automatically caught. All errors happening outside of them will need to be handled explicitly.
Will there ever be any scenario where a particular error/exception is thrown that the promise's
.catch
fails to catch?
Yes. That backendService.getResults(input)
call might not return a promise, but it can throw an exception. Or it doesn't even get that far when backendService
is null, and you'll get a ReferenceError
or .getResults
is not a function and you'll get a TypeError
.
is that try/catch really necessary?
Not really. In the latter case, that your code has a grave mistake, you probably don't care to throw and crash. The former case, that backendService.getResults(input)
throws, is heavily despised. Asynchronous functions should never throw
but only return promises - exactly for the reason that you don't have to write two error handling statements then.
well... it's defensive coding, right? It's not a Bad Thing.
Yeah, pretty much. But it is questionable here. A synchronous exceptions is really unexpected here, not just a service whose failure can be handled. The logging message in the catch
block should signify that.
Notice that it also isn't defensive enough. It doesn't catch the probably more likely mistake where getResults()
does return, but something that is not a promise. Calling .then()
on that might throw. Similarly, the if (promise !== null)
is dubious, as it hides when null
is returned erroneously (we really could need try-catch-else
here).
is that try/catch really necessary?
Not really. As long as your backendService.getResults()
returns a promise. Like return $http(...)
Will there ever be any scenario where a particular error/exception is thrown that the promise's .catch fails to catch?
I don't think so, since any error will be a rejected promise, it will fall into your .catch()
handler
well... it's defensive coding, right? It's not a Bad Thing.
It depends... Javascript try/catch is has some performance issues. So if you're using just for the sake of making sure, you could remove it :)
Take a further look at try-catch discussion here if you wish: Javascript Try-Catch Performance Vs. Error Checking Code
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With