In this blog post I’ll show how to use promises with AngularJS. First, I’m going to describe a few anti-patterns I’ve seen and then I’ll move on to the core ideas of promise.
So, what’s wrong with this code ?
Well, a few things:
Line 5-9: Creating a promise when using the $http API is pointless. The service is already returning a promise.
Line 11-15: Same problem, different reason. Here there’s no need to create a promise because the .then function will always return a new promise (by definition)
Line 23: Instead of using the hack .then(null, errorHandler) to intercept an error, you should use .catch(errorHandler). I used the word hack because it’s getting around the transition rules.
You have to understand that promises are about something much deeper than callback aggregation. Indeed, it’s more about providing a direct correspondence between synchronous functions and asynchronous functions.
Essentially, the point of promises is to give functional composition and error bubbling in the asynchronous world. So, it leads me to 2 fundamental properties of the promises:
- A promise will always return a new promise. It means that you can directly chain promises. You don’t have to explicitly create a new promise every time you want to chain two calls.
- A promise is rejected when an exception is thrown. Basically, if an exception is thrown the chain will be interrupted until the exception is caught. There’s no need to define an error handler for every call.
By the way, it’s also important to know that a promise can be in 3 different states only: pending, fulfilled, rejected. And that the transition rules are:
- When pending, it may transition to either the fulfilled or rejected state.
- When fulfilled or rejected, a promise can NOT transition to any other state.
Line 5, 8, 11: No need to create a promise using $q.defer() because the $http service already returns a promise.
Line 15, 27, 28: Even though the refreshNewsList doesn’t explicitly return a promise, based on the definition the then will do it. That’s why we can still chain the calls.
Line 29: If an error occurs, it will execute errorHandler. There’s no need to specify the handler for every every step!
Note: You can also play with the JSFiddle.
In conclusion, using promises with Angular isn’t really difficult. You just need to understand the real motivations. So keep in mind that a promise:
- has a then method that returns a new promise
- is fulfilled when the callback is finished
- moves to the failed state when an exception is thrown
- is about functional composition and error bubbling