{"id":1581,"date":"2022-01-20T13:04:07","date_gmt":"2022-01-20T12:04:07","guid":{"rendered":"https:\/\/nguenkam.com\/blog\/?p=1581"},"modified":"2023-12-14T01:11:04","modified_gmt":"2023-12-14T00:11:04","slug":"ngzone-how-and-when-to-use-it-in-angular","status":"publish","type":"post","link":"https:\/\/nguenkam.com\/blog\/index.php\/2022\/01\/20\/ngzone-how-and-when-to-use-it-in-angular\/","title":{"rendered":"NgZone in Angular: How and when to use it."},"content":{"rendered":"\n<p>A zone is&nbsp;<strong>an execution context that persists across async tasks<\/strong>. You can think of it as thread-local storage for JavaScript VMs. Zones in Zone.js are hierarchical. This means that&nbsp;<strong>new zones are created by &#8220;forking&#8221; an existing zone<\/strong>. When you fork a zone, the&nbsp;<strong>new zone inherits the behaviours<\/strong>&nbsp;of its parent but can also have additional behaviours or modifications.<\/p>\n\n\n\n<h4><strong>NgZone <\/strong><\/h4>\n\n\n\n<p>In the context of Angular, the framework doesn\u2019t directly use the root zone. Instead,&nbsp;<strong>Angular creates its specialized zone by forking the root zone<\/strong>.<\/p>\n\n\n\n<p>This forked zone, known as NgZone or sometimes referred to as the &#8220;inner zone,&#8221; is augmented with Angular-specific behaviors. It&#8217;s within this NgZone that Angular&nbsp;<strong>tracks changes and decides when to run its change detection.<\/strong><\/p>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h4>NgZone&nbsp;<code>run()<\/code>&nbsp;and&nbsp;<code>runOutsideOfAngular()<\/code><\/h4>\n\n\n\n<p><code>Zone<\/code>&nbsp;handles most asynchronous APIs such as&nbsp;<code>setTimeout()<\/code>,&nbsp;<code>Promise.then()<\/code>, and&nbsp;<code>addEventListener()<\/code>. For the full list, see the&nbsp;<a href=\"https:\/\/github.com\/angular\/angular\/blob\/main\/packages\/zone.js\/MODULE.md\">Zone Module document<\/a>. In those asynchronous APIs, we don&#8217;t need to trigger change detection manually.<\/p>\n\n\n\n<p>Some third party APIs are not handled by Zone. In those cases, the&nbsp;<code><a href=\"https:\/\/angular.io\/api\/core\/NgZone\">NgZone<\/a><\/code>&nbsp;service provides a&nbsp;<a href=\"https:\/\/angular.io\/api\/core\/NgZone#run\"><code>run()<\/code><\/a>&nbsp;method that allows us to run a function inside the Angular zone. This function, and all asynchronous operations in that function, triggers change detection automatically at the correct time.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>export class AppComponent implements OnInit {\n  constructor(private ngZone: NgZone) {}\n  ngOnInit() {\n    \/\/ New async API is not handled by Zone, so you need to use ngZone.run()\n    \/\/ to make the asynchronous operation callback in the Angular zone and\n    \/\/ trigger change detection automatically.\n    someNewAsyncAPI(() =&gt; {\n      this.ngZone.<span class=\"has-inline-color has-luminous-vivid-orange-color\">run<\/span>(() =&gt; {\n        \/\/ update the data of the component\n      });\n    });\n  }\n}<\/code><\/pre>\n\n\n\n<p>By default, all asynchronous operations are inside the Angular zone, which triggers change detection automatically. Another common case is when you don&#8217;t want to trigger change detection. In that situation, you can use another&nbsp;<code><a href=\"https:\/\/angular.io\/api\/core\/NgZone\">NgZone<\/a><\/code>&nbsp;method:&nbsp;<a href=\"https:\/\/angular.io\/api\/core\/NgZone#runoutsideangular\"><code>runOutsideAngular()<\/code><\/a>.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>export class AppComponent implements OnInit {\n  constructor(private ngZone: NgZone) {}\n  ngOnInit() {\n    \/\/ You know no data will be updated,\n    \/\/ so you don't want to trigger change detection in this\n    \/\/ specified operation. Instead, call ngZone.runOutsideAngular()\n    this.ngZone.<span class=\"has-inline-color has-luminous-vivid-orange-color\">runOutsideAngular<\/span>(() =&gt; {\n      setTimeout(() =&gt; {\n        \/\/ update component data\n        \/\/ but don't trigger change detection.\n      });\n    });\n  }\n}<\/code><\/pre>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h4>Setting up Zone.js<\/h4>\n\n\n\n<p>To make Zone.js available in Angular, we need to import the&nbsp;<code>zone.js<\/code>&nbsp;package. If we are using the Angular CLI, this step is done automatically, and we can see the following line in the&nbsp;<code>src\/polyfills.ts<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/***************************************************************************************************\n * Zone JS is required by default for Angular itself.\n *\/\nimport 'zone.js';  \/\/ Included with Angular CLI.<\/code><\/pre>\n\n\n\n<p>Before importing the&nbsp;<code>zone.js<\/code>&nbsp;package, we can set the following configurations:<\/p>\n\n\n\n<ul><li>Disabling some asynchronous API monkey patching for better performance. For example, disabling the&nbsp;<code>requestAnimationFrame()<\/code>&nbsp;monkey patch, so the callback of&nbsp;<code>requestAnimationFrame()<\/code>&nbsp;does not trigger change detection. This is useful if, in our application, the callback of the&nbsp;<code>requestAnimationFrame()<\/code>&nbsp;does not update any data.<\/li><li>Specify that certain DOM events do not run inside the Angular zone. For example, to prevent a&nbsp;<code>mousemove<\/code>&nbsp;or&nbsp;<code>scroll<\/code>&nbsp;event to trigger change detection<\/li><\/ul>\n\n\n\n<p><\/p>\n\n\n\n<p>Several other settings can be changed. To make these changes, we need to create a&nbsp;<code><strong><em>zone-flags.ts<\/em><\/strong><\/code>&nbsp;file, such as the following.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ disable patching requestAnimationFrame\n(window as any).__Zone_disable_requestAnimationFrame = true;\n\n\/\/ disable patching specified eventNames\n(window as any).__zone_symbol__UNPATCHED_EVENTS = &#91;'scroll', 'mousemove'];<\/code><\/pre>\n\n\n\n<p><\/p>\n\n\n\n<p>Next, import&nbsp;<code>zone-flags<\/code>&nbsp;before we import&nbsp;<code>zone.js<\/code>&nbsp;in the&nbsp;<code>polyfills.ts<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/***************************************************************************************************\n * Zone JS is required by default for Angular.\n *\/\nimport `.\/zone-flags`;\nimport 'zone.js';  \/\/ Included with Angular CLI.<\/code><\/pre>\n\n\n\n<p><em>For more information about what we can configure, see the&nbsp;<a href=\"https:\/\/github.com\/angular\/angular\/tree\/main\/packages\/zone.js\">Zone.js<\/a>&nbsp;documentation.<\/em><\/p>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h4><span class=\"has-inline-color has-vivid-red-color\">Summary<\/span><\/h4>\n\n\n\n<p><strong><em>runOutsideAngular<\/em><\/strong> can be used to run code outside of Angular so it doesn&#8217;t trigger change detection unnecessarily. This can be used for example to run multiple HTTP requests to get all the data before rendering it. <\/p>\n\n\n\n<p>To run the code again in Angular, NgZone&#8217;s <strong><em>run <\/em><\/strong>method can be used.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import {\n Component,\n OnInit,\n NgZone\n}\n from '@angular\/core';\n\n@Component({\n    ...\n})  \n\nexport class Mycomponent implements OnInit {\n constructor(private zone: NgZone) {}\n    ngOnInit() {\n\n     this.zone.<span class=\"has-inline-color has-luminous-vivid-amber-color\"><strong><em>runOutsideAngular<\/em><\/strong><\/span>(() =&gt; {\n\n             \/\/write here any bussiness Logic, you want to compute outside Angular\n            ).subscribe(() =&gt; {\n              \/\/ do nothing on success or compute some other logis\n            }, (e: Error) =&gt; {\n              this.zone.<span class=\"has-inline-color has-luminous-vivid-amber-color\"><strong><em>run<\/em><\/strong><\/span>(() =&gt; {\n\n                \/\/Here you can now run your code in Angular\n                this.connectionSubject.next(ConnectionState.DISCONNECTING);\n              });\n            });\n          });\n  }\n\n}\n\n<\/code><\/pre>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h4>NoopZone<\/h4>\n\n\n\n<p><code>Zone<\/code>&nbsp;helps Angular know when to trigger change detection and let the developers focus on the application development. By default,&nbsp;<code>Zone<\/code>&nbsp;is loaded and works without further configuration. We don&#8217;t necessarily have to use&nbsp;<code>Zone<\/code>&nbsp;to make Angular work. Instead, we can opt to trigger change detection on our own.<\/p>\n\n\n\n<p>To remove Zone.js, make the following changes.<\/p>\n\n\n\n<ol><li>Remove the&nbsp;<code>zone.js<\/code>&nbsp;import from&nbsp;<code>polyfills.ts<\/code>:<\/li><\/ol>\n\n\n\n<pre class=\"wp-block-code\"><code>\/***************************************************************************************************\n * Zone JS is required by default for Angular itself.\n *\/\n\/\/ import 'zone.js';  \/\/ Included with Angular CLI.<\/code><\/pre>\n\n\n\n<p>2. Bootstrap Angular with the&nbsp;<code>noop<\/code>&nbsp;zone in&nbsp;<code>src\/main.ts<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>platformBrowserDynamic().bootstrapModule(AppModule, { ngZone: 'noop' })\n.catch(err =&gt; console.error(err));<\/code><\/pre>\n\n\n\n<p><\/p>\n\n\n\n<p><strong><span class=\"has-inline-color has-vivid-red-color\"><code>PS:<\/code><\/span><span class=\"has-inline-color has-luminous-vivid-orange-color\"> <\/span><\/strong><em><span class=\"has-inline-color has-luminous-vivid-orange-color\">Disabling&nbsp;<code>Zone<\/code>&nbsp;requires you to trigger all change detection at the correct timing yourself, which requires comprehensive knowledge of change detection.<\/span><\/em><\/p>\n","protected":false},"excerpt":{"rendered":"<p>A zone is&nbsp;an execution context that persists across async tasks. You can think of it as thread-local storage for JavaScript VMs. Zones in Zone.js are hierarchical. This means that&nbsp;new zones are created by &#8220;forking&#8221; an existing zone. When you fork a zone, the&nbsp;new zone inherits the behaviours&nbsp;of its parent but can also have additional behaviours [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":1965,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[37,5],"tags":[451,449,452,450],"_links":{"self":[{"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/posts\/1581"}],"collection":[{"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/comments?post=1581"}],"version-history":[{"count":7,"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/posts\/1581\/revisions"}],"predecessor-version":[{"id":3057,"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/posts\/1581\/revisions\/3057"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/media\/1965"}],"wp:attachment":[{"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/media?parent=1581"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/categories?post=1581"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/tags?post=1581"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}