Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Zones in angular

  1. What are zones?
  2. How are angular ngZone differ from zone.js?
  3. When should they be used? Can someone help with practical examples of using ngZone?

I've gone through angular documentation here however, I couldn't get complete understanding.

https://angular.io/api/core/NgZone

like image 848
Jyoti Prasad Pal Avatar asked Aug 27 '17 09:08

Jyoti Prasad Pal


People also ask

What is use of zone js in Angular?

js provides a mechanism, called zones, for encapsulating and intercepting asynchronous activities in the browser (e.g. setTimeout , , promises). These zones are execution contexts that allow Angular to track the start and completion of asynchronous activities and perform tasks as required (e.g. change detection). Zone.

What is the purpose of zone dependency in Angular project?

Angular uses the zone to patch async APIs(addEventListener, setTimeout(), ...) and uses notifications from these patched APIs to run change detection every time some async event happened. Also zonejs is useful for debugging, testing, profiling. It helps you see whole call stack if you face with some error.

Do I need Zone js for Angular?

* Zone JS is required by Angular itself. */ import 'zone. js/dist/zone'; // Included with Angular CLI. platformBrowserDynamic() .

What is Zone Evergreen?

Evergreen, Colorado is in USDA Hardiness Zones 5a and 5b A hardiness zone is a geographically defined area in which a specific category of plant life is capable of growing, as defined by climatic conditions, including its ability to withstand the minimum temperatures of the zone.


2 Answers

NgZone is a wrapper around Zone.js which is a library that creates a context around asynchronous functions in order to make them trackable.

Angular's change detection is heavily dependent on Zones, How?

Angular needs a way of understanding when's the time to run the change detection, which is basically nothing but updating the DOM to represent the latest model ( javascript ) changes.

Imagine we have bellow example :

  <div id="content"></div>

And somewhere in our javascript code, we have

const element = document.getElementById('content');

function updateText(){
     element.innerHtml = myText+ ": updated at time"+Date.now()
}

Let's say initially I'm going to update the content with a hello :

  const myText = "Hello";

  this.updateText();

This will update my HTML content to the text: "Hello updated at time 19:30"

and then let's say I want to update the myText variable to be something else after a user click :

  <button onClick="updateTheTextAgain()"></button>



  updateTheTextAgain(){

     this.myText = "Hi there";
  }

What's gonna happen if I click on that button?

Nothing;

Well, actually, it's not, "nothing", I managed to update the variable, but I did NOT update the view ( I didn't detect the changes of the model), so I need to tweak my updateTheTextAgain to be :

   updateTheTextAgain(){

     this.myText = "Hi there";
       this.updateText(); /// Making sure I'm detecting the change ( I'm updating the `DOM`)

  }

Now, clicking the button will update my view (because of the manual change detection).

This obviously is not the best idea, because then I have to write a lot of updateText functions and call them anywhere that I want the view to be updated after I update the model, right ( Go back to Angular1 and remember $scope.apply())?

Here is where ZoneJs is amazing.

Imagine if I could rewrite the onClick function, I mean the original onClick function of the browser to be :

 const originalOnClick = window.onClick;


 window.onClick = function(){
    originalOnClick();
    this. updateText();
 }

This is called monkey patching or open heart surgery of native functions.

What am I getting by this?

After I put my patched onClick in the page, all the onClick function that is going to be written in the whole application, are going to go through my patched onClick, which means, I don't have to run updateText() function anymore after every onclick, because it's baked into the click event handler itself.

In Angular, that updateText is the change detection, Angular has hooks in all the native events ( by using Zones).

So when you write :

   setTimeout(()=>{
        console.log('Do something');

   },100);

What you're actually writing is something like :

   setTimeout(()=>{
        console.log('Do something');
        runAngularsChangeDetection(); 
   },100);

Above is far away what is happening in reality, but it's the heart of the whole story of change detection and Zones and why do we need them/

** UPDATE:**

When should we use NgZone.

There would be a lot of cases when you want to use NgZone, I can name two :

1- When you want something to run outside of Angular's change detection :

Remember I said Angular has hooks in all async events? window.onScroll is one of them, now let's say we want to do some calculation when the user is scrolling, what you normally do is :

   window.onscroll = ()=>{

    // do some heavy calculation : 
  }     

Now, when scrolling, your function is being called normally as you would expect, but you might notice you're getting a bit of performance issue and that could be because Angular is running the changeDetection on every single scroll event ( expected behaviour).

If you have a lot of binding in your component, then you'll definitely notice the performance drop there on the scroll.

So one way is to say, hey Angular, ignore my onscroll event, I know what I'm doing, I don't want you to run change detection, in this case, you'd use NgZone

 constructor(private zone:NgZone){
   this.zone.runOutsideOfAngular(()=>{
      window.onscroll = ()=>{
       // do some heavy calculation : 
      }
    })
  }

This will make sure Angular won't run the change detection up on scrolling.

Another case would be the exact opposite of above, where you have a function that is somehow outside of Angular's zone and you want it to be inside, like when a third party library is doing some stuff for you and you want it to be bound to your Angular cycle.

   this.zone.run(()=>{
        $.get('someUrl').then(()=>{
           this.myViewVariable = "updated";
        })
   });

Without using Zone, you most likely need to do :

         $.get('someUrl').then(()=>{
           this.myViewVariable = "updated";
           this.changeDetectorRef.detectChanges();
        })

But note that when your function is inside the zone ( the run method ) you don't have to call the detectChanges manually yourself and angular will do the job

like image 61
Milad Avatar answered Sep 18 '22 14:09

Milad


Current official document is not up to the mark. There are people who do crazy stuffs in Angular and so does Pascal Precht. His below article will help you to understand what is Zone and ngZone.

https://blog.thoughtram.io/angular/2016/02/01/zones-in-angular-2.html

like image 45
Nikhil Shah Avatar answered Sep 21 '22 14:09

Nikhil Shah