diff --git a/aio/content/guide/zone.md b/aio/content/guide/zone.md index 9297acd160..68aa2faec1 100644 --- a/aio/content/guide/zone.md +++ b/aio/content/guide/zone.md @@ -47,7 +47,7 @@ To clarify how changes are detected and values updated, consider the following c } } - // example 1: update data inside button click event handler + // Example 1: update data inside button click event handler document.getElementById('btn').addEventListener('click', () => { // update value value = 'button update value'; @@ -55,7 +55,7 @@ To clarify how changes are detected and values updated, consider the following c detectChange(); }); - // example 2: Http Request + // Example 2: HTTP Request const xhr = new XMLHttpRequest(); xhr.addEventListener('load', function() { // get response from server @@ -66,7 +66,7 @@ To clarify how changes are detected and values updated, consider the following c xhr.open('GET', serverUrl); xhr.send(); - // example 3: setTimeout + // Example 3: setTimeout setTimeout(() => { // update value inside setTimeout callback value = 'timeout update value'; @@ -74,18 +74,18 @@ To clarify how changes are detected and values updated, consider the following c detectChange(); }, 100); - // example 4: Promise.then - Promise.resolve('promise resolved a value').then((v) => { + // Example 4: Promise.then + Promise.resolve('promise resolved a value').then(v => { // update value inside Promise thenCallback value = v; // call detectChange manually detectChange(); }, 100); - // example 5: some other asynchronous APIs + // Example 5: some other asynchronous APIs document.getElementById('canvas').toBlob(blob => { // update value when blob data is created from the canvas - value = `value updated by canvas, size is ${blog.size}`; + value = `value updated by canvas, size is ${blob.size}`; // call detectChange manually detectChange(); }); @@ -108,7 +108,7 @@ To understand how change detection works, first consider when the application ne -3. Http Data Request. You can also get data from a server through an Http request. For example: +3. HTTP Data Request. You can also get data from a server through an HTTP request. For example: ```typescript @Component({ @@ -129,7 +129,7 @@ export class AppComponent implements OnInit { } ``` -4. MacroTasks, such as `setTimeout()`/`setInterval()`. You can also update the data in the callback function of `macroTask` such as `setTimeout()`. For example: +4. MacroTasks, such as `setTimeout()` or `setInterval()`. You can also update the data in the callback function of a `macroTask` such as `setTimeout()`. For example: ```typescript @Component({ @@ -148,7 +148,7 @@ export class AppComponent implements OnInit { } ``` -5. MicroTask, such as `Promise.then()`. Other asynchronous APIs return a Promise object (such as `fetch`), so the `then()` callback function can also update the data. For example: +5. MicroTasks, such as `Promise.then()`. Other asynchronous APIs return a Promise object (such as `fetch`), so the `then()` callback function can also update the data. For example: ```typescript @Component({ @@ -167,27 +167,23 @@ export class AppComponent implements OnInit { } ``` -6. Other async operations. In addition to `addEventListener()`/`setTimeout()`/`Promise.then()`, there are other operations that can update the data asynchronously. Some examples include `WebSocket.onmessage()` and `Canvas.toBlob()`. +6. Other async operations. In addition to `addEventListener()`, `setTimeout()` and `Promise.then()`, there are other operations that can update the data asynchronously. Some examples include `WebSocket.onmessage()` and `Canvas.toBlob()`. The preceding list contains most common scenarios in which the application might change the data. Angular runs change detection whenever it detects that data could have changed. -The result of change detection is that DOM is updated with new data. Angular detects the changes in different ways. For component initialization, Angular calls change detection explicitly. For [asynchronous operations](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous), Angular uses a Zone to detect changes in places where the data could have possibly mutated and it runs change detection automatically. +The result of change detection is that the DOM is updated with new data. Angular detects the changes in different ways. For component initialization, Angular calls change detection explicitly. For [asynchronous operations](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous), Angular uses a zone to detect changes in places where the data could have possibly mutated and it runs change detection automatically. ## Zones and execution contexts -A zone provides an execution context that persists across async tasks. [Execution Context](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this) is an abstract concept that holds information about the environment within the current code being executed. Consider the following example. +A zone provides an execution context that persists across async tasks. [Execution Context](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this) is an abstract concept that holds information about the environment within the current code being executed. Consider the following example: ```javascript const callback = function() { console.log('setTimeout callback context is', this); } -const ctx1 = { - name: 'ctx1' -}; -const ctx2 = { - name: 'ctx2' -}; +const ctx1 = { name: 'ctx1' }; +const ctx2 = { name: 'ctx2' }; const func = function() { console.log('caller context is', this); @@ -198,8 +194,8 @@ func.apply(ctx1); func.apply(ctx2); ``` -The value of `this` in the callback of `setTimeout` might differ depending on when `setTimeout` is called. -Thus you can lose the context in asynchronous operations. +The value of `this` in the callback of `setTimeout()` might differ depending on when `setTimeout()` is called. +Thus, you can lose the context in asynchronous operations. A zone provides a new zone context other than `this`, the zone context that persists across asynchronous operations. In the following example, the new zone context is called `zoneThis`. @@ -227,19 +223,19 @@ Zone.js can create contexts that persist across asynchronous operations as well const zone = Zone.current.fork({ name: 'zone', onScheduleTask: function(delegate, curr, target, task) { - console.log('new task is scheduled: ', task.type, task.source); + console.log('new task is scheduled:', task.type, task.source); return delegate.scheduleTask(target, task); }, onInvokeTask: function(delegate, curr, target, task, applyThis, applyArgs) { - console.log('task will be invoked', task.type, task.source); + console.log('task will be invoked:', task.type, task.source); return delegate.invokeTask(target, task, applyThis, applyArgs); }, onHasTask: function(delegate, curr, target, hasTaskState) { - console.log('task state changed in the zone', hasTaskState); + console.log('task state changed in the zone:', hasTaskState); return delegate.hasTask(target, hasTaskState); }, onInvoke: function(delegate, curr, target, callback, applyThis, applyArgs) { - console.log('the callback will be invoked', callback); + console.log('the callback will be invoked:', callback); return delegate.invoke(target, callback, applyThis, applyArgs); } }); @@ -252,43 +248,43 @@ zone.run(() => { The above example creates a zone with several hooks. -`onXXXTask` hooks trigger when the status of Task changes. -The Zone Task concept is very similar to the Javascript VM Task concept. -- `macroTask`: such as `setTimeout()`. -- `microTask`: such as `Promise.then()`. -- `eventTask`: such as `element.addEventListener()`. +The `onXXXTask` hooks trigger when the status of the task changes. +The concept of a *Zone Task* is very similar to the JavaScript VM Task concept: +- `macroTask`: such as `setTimeout()` +- `microTask`: such as `Promise.then()` +- `eventTask`: such as `element.addEventListener()` These hooks trigger under the following circumstances: - `onScheduleTask`: triggers when a new asynchronous task is scheduled, such as when you call `setTimeout()`. - `onInvokeTask`: triggers when an asynchronous task is about to execute, such as when the callback of `setTimeout()` is about to execute. -- `onHasTask`: triggers when the status of one kind of task inside a zone changes from stable to unstable or from unstable to stable. A status of stable means there are no tasks inside the Zone, while unstable means a new task is scheduled in the zone. +- `onHasTask`: triggers when the status of one kind of task inside a zone changes from stable to unstable or from unstable to stable. A status of "stable" means there are no tasks inside the zone, while "unstable" means a new task is scheduled in the zone. - `onInvoke`: triggers when a synchronous function is going to execute in the zone. With these hooks, `Zone` can monitor the status of all synchronous and asynchronous operations inside a zone. -The above example returns the following output. +The above example returns the following output: ``` -the callback will be invoked () => { +the callback will be invoked: () => { setTimeout(() => { console.log('timeout callback is invoked.'); }); } -new task is scheduled: macroTask setTimeout -task state changed in the zone { microTask: false, +new task is scheduled: macroTask setTimeout +task state changed in the zone: { microTask: false, macroTask: true, eventTask: false, change: 'macroTask' } -task will be invoked macroTask setTimeout +task will be invoked macroTask: setTimeout timeout callback is invoked. -task state changed in the zone { microTask: false, +task state changed in the zone: { microTask: false, macroTask: false, eventTask: false, change: 'macroTask' } ``` -All of the functions of Zone are provided by a library called [zone.js](https://github.com/angular/angular/tree/master/packages/zone.js/README.md). +All of the functions of `Zone` are provided by a library called [Zone.js](https://github.com/angular/angular/tree/master/packages/zone.js/README.md). This library implements those features by intercepting asynchronous APIs through monkey patching. Monkey patching is a technique to add or modify the default behavior of a function at runtime without changing the source code. @@ -300,14 +296,14 @@ This service creates a zone named `angular` to automatically trigger change dete 1. When a sync or async function is executed. 1. When there is no `microTask` scheduled. -### NgZone `run()`/`runOutsideOfAngular()` +### NgZone `run()` and `runOutsideOfAngular()` `Zone` handles most asynchronous APIs such as `setTimeout()`, `Promise.then()`, and `addEventListener()`. For the full list, see the [Zone Module document](https://github.com/angular/angular/blob/master/packages/zone.js/MODULE.md). Therefore in those asynchronous APIs, you don't need to trigger change detection manually. There are still some third party APIs that Zone does not handle. -In those cases, the NgZone service provides a [`run()`](api/core/NgZone#run) method that allows you to execute a function inside the angular zone. +In those cases, the `NgZone` service provides a [`run()`](api/core/NgZone#run) method that allows you to execute a function inside the angular zone. This function, and all asynchronous operations in that function, trigger change detection automatically at the correct time. ```typescript @@ -328,7 +324,7 @@ export class AppComponent implements OnInit { By default, all asynchronous operations are inside the angular zone, which triggers change detection automatically. Another common case is when you don't want to trigger change detection. -In that situation, you can use another NgZone method: [runOutsideAngular()](api/core/NgZone#runoutsideangular). +In that situation, you can use another `NgZone` method: [`runOutsideAngular()`](api/core/NgZone#runoutsideangular). ```typescript export class AppComponent implements OnInit { @@ -349,7 +345,7 @@ export class AppComponent implements OnInit { ### Setting up Zone.js -To make Zone.js available in Angular, you need to import the zone.js package. +To make Zone.js available in Angular, you need to import the `zone.js` package. If you are using the Angular CLI, this step is done automatically, and you will see the following line in the `src/polyfills.ts`: ```typescript @@ -364,17 +360,20 @@ Before importing the `zone.js` package, you can set the following configuration - You can disable some asynchronous API monkey patching for better performance. For example, you can disable the `requestAnimationFrame()` monkey patch, so the callback of `requestAnimationFrame()` will not trigger change detection. This is useful if, in your application, the callback of the `requestAnimationFrame()` will not update any data. -- You can specify that certain DOM events not run inside the angular zone; for example, to prevent a `mousemove` or `scroll` event to trigger change detection. +- You can specify that certain DOM events do not run inside the angular zone; for example, to prevent a `mousemove` or `scroll` event to trigger change detection. There are several other settings you can change. To make these changes, you need to create a `zone-flags.ts` file, such as the following. ```typescript - (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame - (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames +// disable patching requestAnimationFrame +(window as any).__Zone_disable_requestAnimationFrame = true; + +// disable patching specified eventNames +(window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; ``` -Next, import `zone-flags` before you import `zone` in the `polyfills.ts`. +Next, import `zone-flags` before you import `zone.js` in the `polyfills.ts`: ```typescript /*************************************************************************************************** @@ -384,12 +383,12 @@ import `./zone-flags`; import 'zone.js/dist/zone'; // Included with Angular CLI. ``` -For more information of what you can configure, see the [zone.js](https://github.com/angular/angular/tree/master/packages/zone.js) documentation. +For more information about what you can configure, see the [Zone.js](https://github.com/angular/angular/tree/master/packages/zone.js) documentation. ### NoopZone `Zone` helps Angular know when to trigger change detection and let the developers focus on the application development. -By default, `Zone` is loaded and works without additional configuration. However, you don't have to use `Zone` to make Angular work, instead opting to trigger change detection on your own. +By default, `Zone` is loaded and works without additional configuration. However, you don't necessarily have to use `Zone` to make Angular work. Instead, you can opt to trigger change detection on your own.
@@ -399,9 +398,9 @@ By default, `Zone` is loaded and works without additional configuration. However
-To remove `zone.js`, make the following changes. +To remove Zone.js, make the following changes. -1. Remove the `zone.js` import from `polyfills.ts`. +1. Remove the `zone.js` import from `polyfills.ts`: ```typescript /*************************************************************************************************** @@ -410,9 +409,9 @@ To remove `zone.js`, make the following changes. // import 'zone.js/dist/zone'; // Included with Angular CLI. ``` -2. Bootstrap Angular with `noop zone` in `src/main.ts`. +2. Bootstrap Angular with the `noop` zone in `src/main.ts`: ```typescript - platformBrowserDynamic().bootstrapModule(AppModule, {ngZone: 'noop'}) + platformBrowserDynamic().bootstrapModule(AppModule, { ngZone: 'noop' }) .catch(err => console.error(err)); ```