Search code examples
angularangular-changedetectionngzone

When to use zone.run()?


I tried to read a lot about NgZone in angular. I got to know that angular uses zone.js for change detection. I see some code used zone.run and place few actions inside of it.

What does it do actually?

Still I could not figure out the actual use of zone.run

this.zone.run(() => {
     /* my code here */
});

With the help of this link, I understood little bit.


Solution

  • The answer is itself provided in the blog which you have mentioned. I'll try to break it down further. In the given example :

    Situation: You are creating a progress-bar component whose value will be updated every 10 milli seconds

    Without NgZone:

    Once button is clicked , increaseProgress() will be called with a function (whose value will be displayed once the progress bar is complete)

        <button (click)="processWithinAngularZone()">
          Process within Angular zone
        </button>
    

    it calls itself every 10 milli seconds and it keeps on increasing this.progress counter till 100

    increaseProgress(doneCallback: () => void) {
      this.progress += 1;
      console.log(`Current progress: ${this.progress}%`);
    
      if (this.progress < 100) {
        window.setTimeout(() => {
          this.increaseProgress(doneCallback);
        }, 10);
      } else {
        doneCallback();
      }
    }
    

    This will work but since we are using setTimeout, the ChangeDetection cycle will be triggered every 10 milliseconds which will impact performance of application


    With NgZone:

    With ngZone we are passing, zone.run() rather than console.log. This would basically act as a trigger for ChangeDetection once the counter is complete.

    Now, to avoid the effect of setTimeout (which triggers ChangeDetectionbecause of monkey patching), we wrap the entire execution block inside this.zone.runOutsideAngular. The ChangeDetection is only invoked when we explicitly call zone.run().

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

    Similar use case :

    1. Let's say you need to implement some logic on scrollEvent which might trigger a function which could result in triggering of ChangeDetection. To avoid this, we can use zone.runOutsideAngular and manually trigger the ChangeDetection after certain action/duration using zone.run().

    2. You are using some 3rd party library (which works outside of Angular ChangeDetection) and you need to manually trigger CD after some event of that 3rd party library.

    Its not very frequent to use this, but yes , its can create unwanted behaviors when not known.

    I hope it has helped you understand the concept better