An example of performing AJAX requests in Angular is probably the second thing you ever saw when getting into Angular (right after an example showing off two way binding). It does look very sexy and easy when you look at it, since most examples look something like this:
1 2 3
This is usually the first time you learn about promises in Angular and how they work. Later when you get more in depth you’ll realize that only
$http’s promises have
error() functions, while regular promises just have
You might wonder what’s the difference, really. Well, Angular is all about decisions, and this time I want to stress how using
success() is a bad one.
success() is implemented
If we look in Angular’s source code here we can see that
success is basically:
1 2 3 4 5 6 7
So it’s just like
then() but deconstructing the response object. This is essentially just syntax sugar so you’d have a callback that gets the JSON object back as its first argument and save you reaching into
First, I hate anything that creates inconsistency in my code. If we use
success() we’ll still have to use
then() in every other place that has a promise, which makes this syntax sugar more of a cognitive leak in my opinion than anything useful.
Second, it couples your code in a subtle way – you’re telling everyone you’re actually reaching to the network to get something.
Say we have a service for managing some resource:
1 2 3 4 5 6 7
And this is used later like so:
This means that all users of
ProductsService definitely know that
getProduct() goes out to the web to get data. What if you later add caching? What if you decorate
ProductsService with some wrapper and need to chain the promise it returns? If everyone assume your promises have
.success() it’s going to be a PITA.
What I like to do instead
On several projects with multiple teams we’ve found this idiom to be quite nice:
1 2 3 4 5 6 7 8 9
This way, we’re using promise chaining to hide the
$http promise and hide response data except for the JSON itself (e.g. response headers, request config). This means that we later can easily swap the original promises with cached promises, or generate random data with a fake promise when testing. Suddenly no one cares about HTTP.
I’ve found that 99% of the time your callers don’t need/know how to handle HTTP errors anyway, so hiding it works. I prefer to go with generic error handlers where needed.