Photo by Markus Spiske on Unsplash
NgZone and Change Detection in Angular
Learn more about how angular is able to detect changes for asynchronous operations
Table of contents
In this article we will understand about ngZone but first we need to understand what is execution context.
Execution Context
- Execution Context is the environment where the JavaScript file is scanned and is executed. When JavaScript Engine start the execution of the script file, first it reads creates an execution context which contain memory part and code part. In memory part it declares all the variables, functions and in the code part the file is executed line by line and the result is updated in the memory part. To track the functions and execution order engine uses call stack.
All the code we write and execute is running in the execution context. When we run the angular application, Angular create a global execution context and run our code inside it. Then why and where do we need ngZone.
When we are handling events and network requests in angular. The async operations tend to go outside the execution context i.e When we run the ts file, and place a network request, we hit the API endpoint wait for response but by the time we get the response the file is already executed and the result is lost so to track the async functions in Angular we use ngZone library.
NgZone
NgZone service is used in angular to perform change detection for our application as it can track all the synchronous and asynchronous operations in the application. Whenever there is a change happening in the application the NgZone service will invoke the life cycle hooks and angular knows that it needs to update the view. Now the developer can provide the necessary code in the life cycle hooks to update the view according to requirements.
NgZone internally uses Zone.js library to create and maintain the zone. The problem with change detection in angular is that we also need to keep track of synchronous operations and asynchronous operations but the Async operations go out of the present execution context by the time we reach response. Example - In the below image you can see that the Async operations b() and c() are present in different boxes(context).
Zone.js helps to avoid this kind of scenarios.
Zone.js
Zone.js is a JavaScript library helps angular to create Zones. A Zone is execution context that is persistent across all the sync and async tasks. The Zone injects code in to the async functions that hepls angular understand when a async operation is invoked and when it has ended using these hooks angular will be able to identify the end of an async operations will perform change detection on application.
Generally Angular run change detection cycle after one of the following operations.
Component initialization
Event Changes/updates
HTTP Data request
Macro Tasks
Micro Tasks
Other async operations - addEventListener(), setTimeout(), etc.
Using NgZone
NgZone is internally used by angular to perform change detection we need not disturb the flow but there may be cases where we want to explicitly use this service in our component. There was one scenario that I faced which led me to know more about NgZone and it's functions.
When we are using some 3rd party libraries or 3rd party services in our angular application there may be some scenarios that memory leaks happen and the async operations or service execution goes out of the global angular execution context to solve this when we are running the service we make sure that we run it inside the ngZone.run()
function.
- run() - Function accepts a function as a parameter. By running the functions thought run() method allows you to reenter the angular zone if the functions is going outside of the angularZone.
export class ListRenderComponent implements OnInit {
// Inject the service in to component and use it.
constructor(private ngZone: NgZone, private http: HttpClient) { }
ngOnInit(): void {
this.ngZone.run(() => {
this.http.get(`${this.url}/list`);
})
}
}
- runOutsideAngular() - Function accepts a function as a parameter. By running the function through
runOutsideAngular()
allows you to escape the angular zone which will prevent the change detection cycle in angular and error handling.
fetchListAndRender() {
this.ngZone.runOutsideAngular(() => {
this.fetchList();
this.renderList();
})
}
// We can use runOutsideAngular if we are rendering a long list
// of items as rendering last list will trigger many events.
- runGaurded() - It's same as
run()
method but except fact that this function can catch the errors that happens in synchronous events and forward them toonError()
method handling.