docs: add guide on how to run code outside of NgZone (#45880)

Explain the relationship between Angular and Zone.js. Covers how to
discover code that triggers change detection more often than we have to
run it and explain how to run code outside the Angular zone.

PR Close #45880
This commit is contained in:
mgechev
2022-05-04 15:51:41 -07:00
committed by Andrew Kushnir
parent 683895c27f
commit 87e661d16c
2 changed files with 60 additions and 0 deletions
@@ -0,0 +1,60 @@
# Resolving Zone Pollution
**Zone.js** is a signaling mechanism that Angular uses to detect when an application state might have changed. It captures asynchronous operations like `setTimeout`, network requests, and event listeners. Angular schedules change detection based on signals from Zone.js
There are cases in which scheduled [tasks](https://developer.mozilla.org/en-US/docs/Web/API/HTML_DOM_API/Microtask_guide#tasks) or [microtasks](https://developer.mozilla.org/en-US/docs/Web/API/HTML_DOM_API/Microtask_guide#microtasks) don’t make any changes in the data model, which makes running change detection unnecessary. Common examples are:
* `requestAnimationFrame`, `setTimeout` or `setInterval`
* Task or microtask scheduling by third-party libraries
This section covers how to identify such conditions, and how to run code outside the Angular zone to avoid unnecessary change detection calls.
## Identifying unnecessary change detection calls
You can detect unnecessary change detection calls using Angular DevTools. Often they appear as consecutive bars in the profiler’s timeline with source `setTimeout`, `setInterval`, `requestAnimationFrame`, or an event handler. When you have limited calls within your application of these APIs, the change detection innovation is usually caused by a third-party library.
<div class="lightbox">
<img alt="Angular DevTools profiler preview showing Zone pollution" src="generated/images/guide/change-detection/zone-pollution.png">
</div>
In the image above, there is a series of change detection calls triggered by event handlers associated with an element. That’s a common challenge when using third-party, non-native Angular components, which do not alter the default behavior of `NgZone`.
## Run tasks outside NgZone
In such cases, we can instruct Angular to avoid calling change detection for tasks scheduled by a given piece of code using [NgZone](https://angular.io/guide/zone).
```ts
import { Component, NgZone, OnInit } from '@angular/core';
@Component(...)
class AppComponent implements OnInit {
constructor(private ngZone: NgZone) {}
ngOnInit() {
this.ngZone.runOutsideAngular(() => setInterval(pollForUpdates), 500);
}
}
```
The snippet above instructs Angular that it should execute the `setInterval` call outside the Angular Zone and skip running change detection after `pollForUpdates` runs.
Third-party libraries commonly trigger unnecessary change detection cycles because they weren't authored with Zone.js in mind. Avoid these extra cycles by calling library APIs outside the Angular zone:
```ts
import { Component, NgZone, OnInit } from '@angular/core';
import * as Plotly from 'plotly.js-dist-min';
@Component(...)
class AppComponent implements OnInit {
constructor(private ngZone: NgZone) {}
ngOnInit() {
this.zone.runOutsideAngular(() => {
Plotly.newPlot('chart', data);
});
}
}
```
Running `Plotly.newPlot('chart', data);` within `runOutsideAngular` instructs the framework that it shouldn’t execute change detection after the execution of tasks scheduled by the initialization logic.
For example, if `Plotly.newPlot('chart', data)` adds event listeners to a DOM element, Angular will not execute change detection after the execution of their handlers.
@reviewed 2022-05-04
Binary file not shown.

After

Width:  |  Height:  |  Size: 131 KiB