diff --git a/modules/angular2/src/core/zone/ng_zone.ts b/modules/angular2/src/core/zone/ng_zone.ts index 7d59044c0d..fbe8504fba 100644 --- a/modules/angular2/src/core/zone/ng_zone.ts +++ b/modules/angular2/src/core/zone/ng_zone.ts @@ -6,13 +6,76 @@ import {wtfLeave, wtfCreateScope, WtfScopeFn} from '../profile/profile'; export interface NgZoneZone extends Zone { _innerZone: boolean; } /** - * A wrapper around zones that lets you schedule tasks after it has executed a task. + * An injectable service for executing work inside or outside of the Angular zone. * - * The wrapper maintains an "inner" and an "mount" `Zone`. The application code will executes - * in the "inner" zone unless `runOutsideAngular` is explicitly called. + * The most common use of this service is to optimize performance when starting a work consisting of + * one or more asynchronous tasks that don't require UI updates or error handling to be handled by + * Angular. Such tasks can be kicked off via {@link #runOutsideAngular} and if needed, these tasks + * can reenter the Angular zone via {@link #run}. * - * A typical application will create a singleton `NgZone`. The outer `Zone` is a fork of the root - * `Zone`. The default `onTurnDone` runs the Angular change detection. + * + * + * ### Example ([live demo](http://plnkr.co/edit/lY9m8HLy7z06vDoUaSN2?p=preview)) + * ``` + * import {Component, View, NgIf, NgZone} from 'angular2/angular2'; + * + * @Component({ + * selector: 'ng-zone-demo' + * }) + * @View({ + * template: ` + *

Demo: NgZone

+ * + *

Progress: {{progress}}%

+ *

Done processing {{label}} of Angular zone!

+ * + * + * + * `, + * directives: [NgIf] + * }) + * export class NgZoneDemo { + * progress: number = 0; + * label: string; + * + * constructor(private _ngZone: NgZone) {} + * + * // Loop inside the Angular zone + * // so the UI DOES refresh after each setTimeout cycle + * processWithinAngularZone() { + * this.label = 'inside'; + * this.progress = 0; + * this._increaseProgress(() => console.log('Inside Done!')); + * } + * + * // Loop outside of the Angular zone + * // so the UI DOES NOT refresh after each setTimeout cycle + * processOutsideOfAngularZone() { + * this.label = 'outside'; + * this.progress = 0; + * this._ngZone.runOutsideAngular(() => { + * this._increaseProgress(() => { + * // reenter the Angular zone and display done + * this._ngZone.run(() => {console.log('Outside Done!') }); + * }})); + * } + * + * + * _increaseProgress(doneCallback: () => void) { + * this.progress += 1; + * console.log(`Current progress: ${this.progress}%`); + * + * if (this.progress < 100) { + * window.setTimeout(() => this._increaseProgress(doneCallback)), 10) + * } else { + * doneCallback(); + * } + * } + * } + * ``` */ export class NgZone { _runScope: WtfScopeFn = wtfCreateScope(`NgZone#run()`); @@ -48,11 +111,7 @@ export class NgZone { _pendingTimeouts: number[] = []; /** - * Associates with this - * - * - a "root" zone, which the one that instantiated this. - * - an "inner" zone, which is a child of the root zone. - * + * @private * @param {bool} enableLongStackTrace whether to enable long stack trace. They should only be * enabled in development mode as they significantly impact perf. */ @@ -77,28 +136,47 @@ export class NgZone { } /** - * Sets the zone hook that is called just before Angular event turn starts. - * It is called once per browser event. + * @private + * + * Sets the zone hook that is called just before a browser task that is handled by Angular + * executes. + * + * The hook is called once per browser task that is handled by Angular. + * + * Setting the hook overrides any previously set hook. */ - overrideOnTurnStart(onTurnStartFn: Function): void { - this._onTurnStart = normalizeBlank(onTurnStartFn); + overrideOnTurnStart(onTurnStartHook: Function): void { + this._onTurnStart = normalizeBlank(onTurnStartHook); } /** - * Sets the zone hook that is called immediately after Angular processes - * all pending microtasks. + * @private + * + * Sets the zone hook that is called immediately after Angular zone is done processing the current + * task and any microtasks scheduled from that task. + * + * This is where we typically do change-detection. + * + * The hook is called once per browser task that is handled by Angular. + * + * Setting the hook overrides any previously set hook. */ - overrideOnTurnDone(onTurnDoneFn: Function): void { - this._onTurnDone = normalizeBlank(onTurnDoneFn); + overrideOnTurnDone(onTurnDoneHook: Function): void { + this._onTurnDone = normalizeBlank(onTurnDoneHook); } /** - * Sets the zone hook that is called immediately after the last turn in - * an event completes. At this point Angular will no longer attempt to - * sync the UI. Any changes to the data model will not be reflected in the - * DOM. `onEventDoneFn` is executed outside Angular zone. + * @private + * + * Sets the zone hook that is called immediately after the `onTurnDone` callback is called and any + * microstasks scheduled from within that callback are drained. + * + * `onEventDoneFn` is executed outside Angular zone, which means that we will no longer attempt to + * sync the UI with any model changes that occur within this callback. * * This hook is useful for validating application state (e.g. in a test). + * + * Setting the hook overrides any previously set hook. */ overrideOnEventDone(onEventDoneFn: Function, opt_waitForAsync: boolean = false): void { var normalizedOnEventDone = normalizeBlank(onEventDoneFn); @@ -114,28 +192,25 @@ export class NgZone { } /** - * Sets the zone hook that is called when an error is uncaught in the - * Angular zone. The first argument is the error. The second argument is - * the stack trace. + * @private + * + * Sets the zone hook that is called when an error is thrown in the Angular zone. + * + * Setting the hook overrides any previously set hook. */ - overrideOnErrorHandler(errorHandlingFn: Function): void { - this._onErrorHandler = normalizeBlank(errorHandlingFn); + overrideOnErrorHandler(errorHandler: (error: Error, stack: string) => void) { + this._onErrorHandler = normalizeBlank(errorHandler); } /** - * Runs `fn` in the inner zone and returns whatever it returns. + * Executes the `fn` function synchronously within the Angular zone and returns value returned by + * the function. * - * In a typical app where the inner zone is the Angular zone, this allows one to make use of the - * Angular's auto digest mechanism. + * Running functions via `run` allows you to reenter Angular zone from a task that was executed + * outside of the Angular zone (typically started via {@link #runOutsideAngular}). * - * ``` - * var zone: NgZone = [ref to the application zone]; - * - * zone.run(() => { - * // the change detection will run after this function and the microtasks it enqueues have - * executed. - * }); - * ``` + * Any future tasks or microtasks scheduled from within this function will continue executing from + * within the Angular zone. */ run(fn: () => any): any { if (this._disabled) { @@ -151,20 +226,16 @@ export class NgZone { } /** - * Runs `fn` in the outer zone and returns whatever it returns. + * Executes the `fn` function synchronously in Angular's parent zone and returns value returned by + * the function. * - * In a typical app where the inner zone is the Angular zone, this allows one to escape Angular's - * auto-digest mechanism. + * Running functions via `runOutsideAngular` allows you to escape Angular's zone and do work that + * doesn't trigger Angular change-detection or is subject to Angular's error handling. * - * ``` - * var zone: NgZone = [ref to the application zone]; + * Any future tasks or microtasks scheduled from within this function will continue executing from + * outside of the Angular zone. * - * zone.runOutsideAngular(() => { - * element.onClick(() => { - * // Clicking on the element would not trigger the change detection - * }); - * }); - * ``` + * Use {@link #run} to reenter the Angular zone and do work that updates the application model. */ runOutsideAngular(fn: () => any): any { if (this._disabled) {