Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When should i use zone.run in angular 2

Tags:

angular

I tried to read a lot about zones in angular 2. I got to know that angular uses of zone.js for change detection. I see some code used zone.run and place few actions inside of it.
What does it do actually? One thing I understood is that it executes these commands as separate block. Still I could not figure out the actual use of zone.run

like image 505
Hacker Avatar asked Sep 06 '17 02:09

Hacker


2 Answers

To learn more about NgZone read:

  • Do you still think that NgZone (zone.js) is required for change detection in Angular?

What does it do actually?

Zone.run allows you to change the current zone. Here is the basic example:

console.log(Zone.current.name);  // <root>
setTimeout(() => console.log(Zone.current.name));  <root>

// we're in the <root> zone now, but when we call `run` on the instance of zone `A` we change the zone
Zone.current.fork({name: 'A'}).run(() => {
    console.log(Zone.current.name); // A
    setTimeout(() => console.log(Zone.current.name)); // A
});

// again we're back in the <root> zone now, but when we call `run` on the instance of zone `B` we change the zone   
Zone.current.fork({name: 'B'}).run(() => {
    console.log(Zone.current.name);  // B
    setTimeout(() => console.log(Zone.current.name)); // B
});

Zone.current.fork creates a new zone. It returns the reference to this new zone and by using run you can execute an asynchronous action inside this zone. You can see above that the setTimeout async task persists correct zone across the time.

Angular creates its own zone:

function forkInnerZoneWithAngularBehavior(zone: NgZonePrivate) {
  zone._inner = zone._inner.fork({
    name: 'angular',
    properties: <any>{'isAngularZone': true},
    ...

And this new zone is what you get when you inject NgZone into class constructors:

constructor (zone: NgZone) {}

You need to use zone.run() when the current execution zone is not Angular zone (NgZone) - Zone.current.name !== 'angular'. If it's the case you need all async tasks scheduled from this zone will not be picked up by Angular and it won't schedule change detection. So you can switch to Angular zone for some async tasks:

Zone.current.fork({name: 'A'}).run(() => {
    // this timeout won't be picked up by Angular
    setTimeout(() => console.log(Zone.current.name)); // A

     // this timeout will be picked up by Angular
     NgZone.run(() => setTimeout(() => console.log(Zone.current.name)));
});

Sometimes you may also do the opposite and run some async tasks outside of Angular zone. Use runOutsideAngular method for that:

NgZone.runOutsideAngular(()=>{ ... })
like image 65
Max Koretskyi Avatar answered Oct 26 '22 13:10

Max Koretskyi


What is Zone.js?

A Zone is an execution context that persists across async tasks. You can think of it as thread-local storage for JavaScript VMs.

How does it work?

zone.js patches most standard web APIs(such as DOM events, XMLHttpRequest...) and nodejs APIs (EventEmitter,fs ...).

How does it apply to Angular?

Angular relies on Zone.js to patch browser events so that it can trigger change detection after the event is complete. This allows you to use POJO (plain old javascript objects).

Note: if you want to see an example of how it patches browser events, try doing an alert(setTimeout)

You may want to use Zone.run to manually trigger change detection for asynchronous events that Angular is unaware of. For example, you may use Zone.run for custom defined events triggered from a 3rd party component.

like image 37
pixelbits Avatar answered Oct 26 '22 13:10

pixelbits