diff --git a/modules/angular2/src/core/zone/vm_turn_zone.dart b/modules/angular2/src/core/zone/vm_turn_zone.dart index e5d0f4e664..70c6388d4d 100644 --- a/modules/angular2/src/core/zone/vm_turn_zone.dart +++ b/modules/angular2/src/core/zone/vm_turn_zone.dart @@ -3,6 +3,21 @@ library angular.zone; import 'dart:async' as async; import 'package:stack_trace/stack_trace.dart' show Chain; +/** + * A [Zone] wrapper that lets you schedule tasks after its private microtask queue is exhausted but + * before the next "VM turn", i.e. event loop iteration. + * + * This lets you freely schedule microtasks that prepare data, and set an [onTurnDone] handler that + * will consume that data after it's ready but before the browser has a chance to re-render. + * + * A VM turn consist of a single macrotask followed 0 to many microtasks. + * + * The wrapper maintains an "inner" and "outer" [Zone]. The application code will executes + * in the "inner" zone unless [runOutsideAngular] is explicitely called. + * + * A typical application will create a singleton [VmTurnZone] whose outer [Zone] is the root [Zone] + * and whose default [onTurnDone] runs the Angular digest. + */ class VmTurnZone { Function _onTurnStart; Function _onTurnDone; @@ -14,12 +29,29 @@ class VmTurnZone { int _nestedRunCounter; + /** + * Associates with this + * + * - an "outer" [Zone], which is the one that created this. + * - an "inner" [Zone], which is a child of the outer [Zone]. + * + * @param {bool} enableLongStackTrace whether to enable long stack trace. They should only be + * enabled in development mode as they significantly impact perf. + */ VmTurnZone({bool enableLongStackTrace}) { _nestedRunCounter = 0; _outerZone = async.Zone.current; _innerZone = _createInnerZoneWithErrorHandling(enableLongStackTrace); } + /** + * Initializes the zone hooks. + * + * @param {Function} onTurnStart called before code executes in the inner zone for each VM turn + * @param {Function} onTurnDone called at the end of a VM turn if code has executed in the inner zone + * @param {Function} onScheduleMicrotask + * @param {Function} onErrorHandler called when an exception is thrown by a macro or micro task + */ initCallbacks({Function onTurnStart, Function onTurnDone, Function onScheduleMicrotask, Function onErrorHandler}) { this._onTurnStart = onTurnStart; this._onTurnDone = onTurnDone; @@ -27,11 +59,45 @@ class VmTurnZone { this._onErrorHandler = onErrorHandler; } + /** + * Runs [fn] in the inner zone and returns whatever it returns. + * + * 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. + * + * ``` + * VmTurnZone zone = ; + * + * void functionCalledFromJS() { + * zone.run(() { + * // auto-digest will run after this function is called from JS + * }); + * } + * ``` + */ dynamic run(fn()) => _innerZone.run(fn); + /** + * Runs [fn] in the outer zone and returns whatever it returns. + * + * In a typical app where the inner zone is the Angular zone, this allows one to escape Angular's + * auto-digest mechanism. + * + * ``` + * void myFunction(VmTurnZone zone, Element element) { + * element.onClick.listen(() { + * // auto-digest will run after element click. + * }); + * zone.runOutsideAngular(() { + * element.onMouseMove.listen(() { + * // auto-digest will NOT run after mouse move + * }); + * }); + * } + * ``` + */ dynamic runOutsideAngular(fn()) => _outerZone.run(fn); - async.Zone _createInnerZoneWithErrorHandling(bool enableLongStackTrace) { if (enableLongStackTrace) { return Chain.capture(() { diff --git a/modules/angular2/src/core/zone/vm_turn_zone.es6 b/modules/angular2/src/core/zone/vm_turn_zone.es6 index e5abf8ebba..69d03ada96 100644 --- a/modules/angular2/src/core/zone/vm_turn_zone.es6 +++ b/modules/angular2/src/core/zone/vm_turn_zone.es6 @@ -1,6 +1,17 @@ import {List, ListWrapper, StringMapWrapper} from 'angular2/src/facade/collection'; import {normalizeBlank, isPresent, global} from 'angular2/src/facade/lang'; +/** + * A wrapper around zones that lets you schedule tasks after it has executed a task. + * + * The wrapper maintains an "inner" and "outer" [Zone]. The application code will executes + * in the "inner" zone unless [runOutsideAngular] is explicitely called. + * + * A typical application will create a singleton [VmTurnZone] whose outer [Zone] is the root [Zone] + * and whose default [onTurnDone] runs the Angular digest. + * + * @exportedAs angular2/core + */ export class VmTurnZone { _outerZone; _innerZone; @@ -11,6 +22,15 @@ export class VmTurnZone { _nestedRunCounter:number; + /** + * Associates with this + * + * - an "outer" zone, which is the one that created this. + * - an "inner" zone, which is a child of the outer zone. + * + * @param {bool} enableLongStackTrace whether to enable long stack trace. They should only be + * enabled in development mode as they significantly impact perf. + */ constructor({enableLongStackTrace}) { this._nestedRunCounter = 0; this._onTurnStart = null; @@ -21,16 +41,54 @@ export class VmTurnZone { this._innerZone = this._createInnerZone(this._outerZone, enableLongStackTrace); } + /** + * Initializes the zone hooks. + * + * @param {Function} onTurnStart called before code executes in the inner zone for each VM turn + * @param {Function} onTurnDone called at the end of a VM turn if code has executed in the inner zone + * @param {Function} onScheduleMicrotask + * @param {Function} onErrorHandler called when an exception is thrown by a macro or micro task + */ initCallbacks({onTurnStart, onTurnDone, onScheduleMicrotask, onErrorHandler} = {}) { this._onTurnStart = normalizeBlank(onTurnStart); this._onTurnDone = normalizeBlank(onTurnDone); this._onErrorHandler = normalizeBlank(onErrorHandler); } + /** + * Runs [fn] in the inner zone and returns whatever it returns. + * + * 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. + * + * ``` + * var zone: VmTurnZone = ; + * + * zone.run(() => { + * // auto-digest will run after this function is called from JS + * }); + * ``` + */ run(fn) { return this._innerZone.run(fn); } + /** + * Runs [fn] in the outer zone and returns whatever it returns. + * + * In a typical app where the inner zone is the Angular zone, this allows one to escape Angular's + * auto-digest mechanism. + * + * ``` + * var zone: VmTurnZone = ; + * + * zone.runOusideAngular(() => { + * element.onClick(() => { + * // Clicking on the element would not trigger the change detection + * }); + * }); + * ``` + */ runOutsideAngular(fn) { return this._outerZone.run(fn); } @@ -86,4 +144,4 @@ export class VmTurnZone { throw e; } } -} \ No newline at end of file +}