# Angular2依赖库之zone.js

《Understanding Zones》一文中,我们通过创建profiling zone了解到了Zones的强大之处。我们知道了Zones 是一种执行过程的上下文，它允许我们hook into我们的异步任务。如果你还没读过该文，我们极度建议您能够先看看，因为本文是基于该文的。在本文中，我们将会进一步的了解Zones在Angular 2中扮演着什么样的角色。

### Angualr的黄金搭档—Zones

It turns out that, the problem that Zones solve, plays very nicely with what Angular needs in order to perform change detection in our applications. Did you ever ask yourself when and why Angular performs change detection? What is it that tells Angular “Dude, a change probably occurred in my application. Can you please check?”.
Before we dive into these questions, let’s first think about what actually causes this change in our applications. Or rather, what can change state in our applications. Application state change is caused by three things:

• Events - User events like click, change, input, submit, …
• XMLHttpRequests - E.g. when fetching data from a remote service
• Timers - setTimeout(), setInterval(), because JavaScript

It turns out that these three things have something in common. Can you name it? … Correct! They are all asynchronous.

Why do you think is this important? Well … because it turns out that these are the only cases when Angular is actually interested in updating the view. Let’s say we have an Angular 2 component that executes a handler when a button is clicked:

@Component({
selector: 'my-component',
template: 
<h3>We love {{name}}</h3>
<button (click)="changeName()">Change name</button>

})
class MyComponent {

name:string = 'thoughtram';

changeName() {
this.name = 'Angular';
}
}

@Component({
selector: 'my-component',
template: 
<h3>We love {{name}}</h3>

})
class MyComponent implements OnInit {

name:string = 'thoughtram';

ngOnInit() {
setTimeout(() => {
this.name = 'Angular';
}, 1000);
}
}

if (this.progress < 100) {
window.setTimeout(() => {
this.increaseProgress(doneCallback);
}, 10);
} else {
doneCallback();
}
}

increaseProgress() calls itself every 10 milliseconds until progress equals 100. Once it’s done, the given doneCallback will execute. Notice how we use setTimeout() to increase the progress.

Running this code in the browser, basically demonstrates what we already know. After each setTimeout() call, Angular performs change detection and updates the view, which allows us to see how progress is increased every 10 milliseconds. It gets more interesting when we run this code outside Angular’s zone. Let’s add a method that does exactly that.

processOutsideAngularZone() {
this.progress = 0;
this.zone.runOutsideAngular(() => {
this.increaseProgress(() => {
this.zone.run(() => {
console.log('Outside Done!');
});
});
});
}

processOutsideAngularZone() also calls increaseProgress() but this time using runOutsideAngularZone() which causes Angular not to be notified after each timeout. We access Angular’s zone by injecting it into our component using the NgZone token.

The UI is not updated as progress increases. However, once increaseProgress() is done, we run another task inside Angular’s zone again using zone.run() which in turn causes Angular to perform change detection which will update the view. In other words, instead of seeing progress increasing, all we see is the final value once it’s done. Check out the running code in action right here.

Zones have now also been proposed as a standard at TC39, maybe another reason to take a closer look at them.

• 评论

• 下一篇