A promise is basically an object with a
then method that represents an operation whose result may be unknown. Whoever has access to the promise can use the
then method to attach callbacks in order to be notified when the operation completes.
Handling Errors in Promise Chains
While promises are great, they also make it rather easy to swallow errors. Using promises means we don’t need to handle errors if we are returning the promise to the caller. This usually makes a lot of sense, for example we might make a request to the server to fetch some data - it is unlikely that we know how the UI should handle a failure at the request level, but the calling code should know how to handle this - and should therefore handle the failure.
In this example, no error handler is attached to the promise returned by
fetchUser. If the operation fails the error will simply disappear. A simple way to handle this would be to alert the error to the user.
Let’s take a look at what the
userService might look like.
fetchUser function does not need to register a callback, since it is returning the promise to the caller - the caller is expected to handle any possible errors.
However, what if we wanted to log any errors that happen during this step? (I’m just using
console.log here, but this could be a logging service like HoneyBadger.) We could possibly implement logging like this:
This implementation will cause massive headaches - if an error occurs it will be logged (as expected), but then the promise will be resolved with the
null value being returned by the
logError function! In order to propagate the error up the chain we need to return a rejected promise (instead of the
null value we are currently returning).
Now the error will be logged and the original caller will still receive a rejected promise, which will trigger the error callback (and display the error to the user in this case).
More features of $q
The $q service has a few more features that are very useful when dealing with asynchronous code. For example, we might want to show a loading indicator to the user when we trigger the request, but we need to ensure that the loading indicator is always hidden when the promise completes (so both for failure and success). We can do this with the
You can find all the code on Plunker. Happy coding.