This article details yet another nice feature that makes your Angular applications in particular cases potentially faster: It lets you resolve multiple
$http responses, that are received around the same time, in one
$digest cycle with a new API added to the
Let’s talk about what that actually means and why you want to do that.
Why and when we need the
In fact, two-way binding is just one kind of binding that Angular supports. We also have one-way bindings and even one-time bindings (since version 1.3) as mentioned earlier. In order to make data binding possible, Angular comes with this sort of event loop (the
$digest) to update our application model and DOM, whenever it is needed.
But how does Angular know, when it has to trigger another
$digest cycle? We don’t want to go in too much detail here, since there are ton of resources out there that cover this topic very well, but let’s clarify at least the most important facts. Some people think initially, that Angular has a kind of poll mechanism that checks every few milliseconds if something on the model changed so it can update the view accordingly. This is not true.
There are basically three possible cases when the state of an application can change and these are the only moments where
$digest cycles are needed. The case are:
- User Interaction through events - The user clicks UI controls like buttons and in turn triggers something in our application that changes state.
- XMLHttpRequests - Also known as AJAX. Something in our app requests some data from a server and update model data accordingly.
- Timeouts - Asynchronous operations cause through timers that can possibly change the state of our application
Whenever one of the above things happens, Angular knows it needs to trigger a
$digest. You might still wonder how that works, since you don’t have to inform Angular about these interactions explicitly. This is because Angular intercepts all of these interactions already for you.
That’s why we have all these predefined directives like
ng-click or even directives that override existing tags like
$http service that Angular brings to the table also makes sure that a
$digest is triggered once a request returns.
In addtion, this explains why you need to call
$scope.$apply(), which in turn triggers a
$digest internally, when you have third-party code that changes your application’s state from the outside world.
Okay, so now we have a general picture of what the
$digest is about and when it’s needed and triggered and also how we can trigger it explicitly with
$scope.$apply. But we haven’t talked about when
$applyAsync comes into play.
$http responses into one
As the name already says,
$applyAsync has something to do with executing a
$scope.$apply through an asynchronous operation. But what does that mean and when makes it actually sense?
We mentioned that one of the cases where a
$digest is triggered, is when an XHR call using
$http service returns from it’s execution. This is nice because we don’t have to worry about updating our model in the DOM once the model is updated. Here’s a small snippet that details that scenario (note that we don’t use
$scope here since we assume that controllerAs syntax is used:
We have a controller that asks for
$http service and uses it to make an XHR to some url and once the call resolves, we update
myModel on our controller with the new data that we got from the server. There’s nothing we need to do to update
myModel in our DOM, since this call, once it resolves, triggers a
$digest that takes care of the rest.
Now imagine we build an application where it’s required to make three XHRs at bootstrap time. That means, three independent requests that all resolve independently after different periods of time, which in turn causes three
$digest cycles that get triggered once each of the calls return. This can slow down our application. Wouldn’t it be nice if we could collect the promises that return from the XHR calls that are made around the same time and resolve them at the next
$digest cycle that happens? Yes! And this is exactly where
$applyAsync comes into play.
Since Angular 1.3,
$rootScope comes with a new method $applyAsync that lets us basically collect expressions. These expressions get immediately evaluated but resolved with the next tick (
$digest). In order to make this work nice with requests that happen through
$httpProvider comes with a corresponding API that tells Angular that we actually want to use that feature.
All we need to do is to call the provider’s useApplyAsync method and Angular takes care of deferring the resolution of your XHR calls to the next tick. Here’s what it looks like:
That’s it! If the application now receives multiple
$http responses at around the same time, this is what happens (a bit simplified though):
- The call’s promise is pushed into a queue
- An asynchronous
$applyis scheduled in case there’s no one scheduled yet, by telling the browser to execute
- Once timed out, the queue is flushed and the actual
setTimeout() is called with a
0 delay which causes an actual delay of around 10 milliseconds depending on the browser. That means, if our three asynchronous calls return at around the same time (somewhere inside that particular timeout delay), they get resolve with a single
$digest cycle instead of three which speeds up our application.
Get updates on new articles and trainings.
Join over 1400 other developers who get our content first.
Disabling Debug Info in Angular 1.3
This article details how to give your app a performance boost in production environments with just a single line of...
Futuristic Routing in Angular
An this article we discuss the new router APIs and how it's going to change the way we implement component...
ngMessages in Angular 1.3
In this article we're going to how the ngMessages module improves the way we handle validation messages when dealing with...
Validators Pipeline in Angular 1.3
In this article we discuss a newly introduced feature called custom validators, so we don't have to hijack parsers and...
Binding to Directive Controllers in Angular 1.3
In this article we are going to take a look how to bind values to directive controllers to make them...
ES6 Style Promises in Angular 1.3
Angular 1.3 starts streamlining its promise APIs with the ES2015 standard. This article details what these additions mean to us....
You might also be interested in
Exploring Angular 1.3: One-time bindingsRead more
Exploring Angular 1.3: ng-model-optionsRead more
Exploring Angular 1.3: Angular-hintRead more
Exploring Angular 1.3: Stateful FiltersRead more
Exploring Angular 1.3: ES6 Style PromisesRead more
Exploring Angular 1.3: Disabling Debug InfoRead more
Exploring Angular 1.3: Binding to Directive ControllersRead more
Exploring Angular 1.3: Validators PipelineRead more
Exploring Angular 1.3: ngMessagesRead more