2014-12-08 17:29:04 -05:00
|
|
|
# Zones
|
|
|
|
|
|
|
|
A Zone is an execution context that persists across async tasks. You can think of it as thread-local storage for
|
2015-03-08 15:35:41 -04:00
|
|
|
JavaScript. Zones are used to intercept all async operation callbacks in the browser. By intercepting async
|
|
|
|
callbacks Angular can automatically execute the change detection at the end of the VM turn to update the application
|
2014-12-08 17:29:04 -05:00
|
|
|
UI bindings. Zones means that in Angular v2 you don't have to remember to call `rootScope.$apply()` in your async call.
|
|
|
|
|
|
|
|
## Execution Context
|
|
|
|
|
|
|
|
```
|
|
|
|
zone['inTheZone'] = false;
|
|
|
|
zone.run(function () {
|
|
|
|
zone['inTheZone'] = true;
|
|
|
|
|
|
|
|
setTimeout(function () {
|
|
|
|
console.log('async in the zone: ' + zone['inTheZone']);
|
|
|
|
}, 0);
|
|
|
|
});
|
|
|
|
|
|
|
|
console.log('sync in the zone: ' + zone['inTheZone']);
|
|
|
|
```
|
|
|
|
|
|
|
|
The above will log:
|
|
|
|
|
|
|
|
```
|
|
|
|
sync in the zone: false
|
|
|
|
async in the zone: true
|
|
|
|
```
|
|
|
|
|
|
|
|
In the above example the `zone` is a global-callback-local variable. To the `zone` we can attach arbitrary properties
|
|
|
|
such as `inTheZone`. When we enter the zone, we get a new `zone` context (which inherits all properties from the
|
|
|
|
parent zone), once we leave the zone, the previous `zone` variable is restored. The key part is that when a async
|
|
|
|
callback is scheduled in the zone, as is the case with `setTimeout`, the current `zone` variable is captured and
|
|
|
|
restored on the callback. This is why the output of the `inTheZone` property inside the callback of the `setTimeout`
|
|
|
|
prints `true`.
|
|
|
|
|
|
|
|
|
|
|
|
## Callback Interception
|
|
|
|
|
|
|
|
In addition to storing properties on the current `zone`, zones can also allow us to intercept all async callbacks
|
|
|
|
and notify us before and after the callback executes.
|
|
|
|
|
|
|
|
```
|
|
|
|
zone.fork({
|
|
|
|
afterTask: function () {
|
|
|
|
// do some cleanup
|
|
|
|
}
|
|
|
|
}).run(function () {
|
|
|
|
// do stuff
|
|
|
|
});
|
|
|
|
```
|
|
|
|
|
|
|
|
The above example will execute the `afterTask` function not only after the `run` finishes, but also after any callback
|
|
|
|
execution which was registered in the `run` block.
|
|
|
|
|
|
|
|
## Putting it all together in Angular
|
|
|
|
|
2015-03-08 15:35:41 -04:00
|
|
|
In Angular2 it is not necessary to notify Angular of changes manually after async callback, because a relevant
|
|
|
|
async callbacks are intercepted. The question is how do we know which callbacks are Angular relevant?
|
2014-12-08 17:29:04 -05:00
|
|
|
|
|
|
|
```
|
|
|
|
/// Some other code running on page can do async operation
|
|
|
|
document.addEventListener('mousemove', function () {
|
|
|
|
console.log('Mouse moved.');
|
|
|
|
});
|
|
|
|
|
|
|
|
var AngularZone = {
|
|
|
|
afterTask: function () {
|
|
|
|
console.log('ANGULAR AUTO-DIGEST!');
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
var ngZone = zone.fork(AngularZone);
|
|
|
|
ngZone.run(function() {
|
|
|
|
console.log('I aware of angular, I should cause digest.');
|
|
|
|
document.addEventListener('click', function () {
|
|
|
|
console.log('Mouse clicked.');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
```
|
|
|
|
|
|
|
|
Will produce:
|
|
|
|
|
|
|
|
```
|
|
|
|
I aware of angular, I should cause digest.
|
|
|
|
ANGULAR AUTO-DIGEST!
|
|
|
|
```
|
|
|
|
|
|
|
|
Moving the mouse will produce many:
|
|
|
|
```
|
|
|
|
Mouse moved.
|
|
|
|
```
|
|
|
|
|
|
|
|
But clicking will produce:
|
|
|
|
```
|
|
|
|
Mouse clicked.
|
|
|
|
ANGULAR AUTO-DIGEST!
|
|
|
|
```
|
|
|
|
|
2015-03-08 15:35:41 -04:00
|
|
|
Notice how the place where the listener was registered will effect whether or not Angular will be notified of the
|
2014-12-08 17:29:04 -05:00
|
|
|
async call and cause a change detection to run to update the UI.
|
|
|
|
|
|
|
|
Being able to globally intercept the async operation is important to have a seamless integration with all existing
|
2015-03-08 15:35:41 -04:00
|
|
|
libraries. But it is equally important to be able to differentiate between Angular and non-Angular code running
|
2014-12-08 17:29:04 -05:00
|
|
|
on the same page concurrently.
|