Книга: Angular 2 Cookbook
Назад: Working with zones outside Angular
Дальше: Execution outside the Angular zone

Listening for NgZone events

With the introduction of Angular 2 comes the concept of zones. Before you begin this recipe, I strongly recommended you to begin by working through the Working with zones outside Angular recipe.

zone.js

zone.js is a library that Angular 2 directly depends upon. It allows Angular to be built upon a zone that allows the framework to intimately manage its execution context.

More plainly, this means that Angular can tell when asynchronous things are happening that it might care about. If this sounds a bit like how $scope.apply() was relevant in Angular 1.x, you are thinking in the right way.

NgZone

Angular 2's integration with zones takes the form of the NgZone service, which acts as a sort of wrapper for the actual Angular zones. This service exposes a useful API that you can tap into.

Note

The code, links, and a live example related to this recipe are available at .

Getting ready

All that is needed for this recipe is a component into which the NgZone service can be injected:

[src/app/app.component.ts]      import {Component} from '@angular/core';      @Component({     selector: 'app-root',     template: ``   })   export class AppComponent {     constructor() {     }   }   

How to do it...

Begin by injecting the NgZone service into your component, which is made available inside the core Angular module:

[src/app/app.component.ts]      import {Component, NgZone} from '@angular/core';      @Component({     selector: 'app-root',     template: ``   })   export class AppComponent {     constructor(private zone:NgZone) {     }   }   

The NgZone service exposes a number of EventEmitters that you can attach to. Since zones are capable of tracking asynchronous activity within it, the NgZone service exposes two EventEmitters that understand when an asynchronous activity becomes enqueued and dequeued as microtasks.

The onUnstable EventEmitter lets you know when one or more microtasks are enqueued; onStable is fired when the the microtask queue is empty and Angular does not plan to enqueue any more.

Add handlers to each:

[src/app/app.component.ts]      import {Component, NgZone} from '@angular/core';      @Component({     selector: 'app-root',     template: ``   })   export class AppComponent {     constructor(private zone:NgZone) {       zone.onStable.subscribe(() => console.log('stable'));       zone.onUnstable.subscribe(() => console.log('unstable'));     }   }   

Terrific! However, the log output of this is quite boring. At application startup, you'll see that the application is reported as stable, but nothing further.

Demonstrating the zone life cycle

If you understand how Angular uses zones, the lack of logging shouldn't surprise you. There's nothing to generate asynchronous tasks in this zone. Go ahead and add some by creating a button with a handler that sets a timeout log statement:

[src/app/app.component.ts]      import {Component, NgZone} from '@angular/core';      @Component({     selector: 'app-root',     template: `<button (click)="foo()">foo</button>`   })   export class AppComponent {     constructor(private zone:NgZone) {       zone.onStable.subscribe(() => console.log('stable'));       zone.onUnstable.subscribe(() => console.log('unstable'));     }        foo() {       setTimeout(() => console.log('timeout handler'), 1000);     }   }   

Now with each click, you should see an unstable-stable pair, followed by an unstable-timeout handler-stable set one second later. This means you've successfully tied into Angular's zone emitters.

How it works...

In order to obviate the necessity of a $scope.apply() construct, Angular needs the ability to intelligently decide when it should check to see whether the state of the application has changed.

In an asynchronous setting, such as a browser environment, this seems like a messy task at first. Something like timed events and input events are, by their very nature, difficult to keep track of. For example, refer to the following code:

element.addEventListener('click', _ => {     // do some stuff     setInterval(_ => {       // do some stuff     }, 1000);   });   

This code is capable of changing the model in two different places, both of which are asynchronous. Code such as this is written all the time and in so many different places; it's difficult to imagine a way of keeping track of such code without sprinkling something like $scope.$apply() all over the place.

The utility of zone.js

The big idea of zones is to give you the ability to grasp how and when the browser is performing asynchronous actions that you care about.

NgZone is wrapping the underlying zone API for you instead of exposing EventEmitters to the various parts of the life cycle, but this shouldn't confuse you one bit. For this example, the log output is demonstrating the following:

  1. The application initializes and examines the application zone. There are no tasks scheduled, so Angular emits a stable event.
  2. You click on the button.
  3. This generates a click event, which in turn generates a task inside the zone to execute the click handler. Angular sees this and emits an unstable event.
  4. The click handler is executed, scheduling a task in 1 second.
  5. The click handler is completed, and the application once again has no pending tasks. Angular emits a stable event.
  6. One second elapses and the browser timer adds the setTimeout handler to the task queue. Since this is shimmed by the zone, Angular sees this occur and emits an unstable event.
  7. The setTimeout handler is executed.
  8. The setTimeout handler is completed, and the application once again has no pending tasks. Angular emits a stable event.

See also

  • Working with zones outside Angular is an excellent introduction to how zones work in the browser
  • Execution outside the Angular zone shows you how to perform long-running operations without incurring a zone overhead
  • Configuring components to use explicit change detection with OnPush describes how to manually control Angular's change detection process
Назад: Working with zones outside Angular
Дальше: Execution outside the Angular zone

thank you
Flame
cant read the code since it is all on a single line. Also this comments section is russian
Rakuneque
DATA COLLECTION AND ANALYSIS Two reviewers extracted data and assessed methodological quality independently lasix torsemide conversion Many others were in that space already