parent
0fc66daef6
commit
abfe175c9e
|
@ -3,6 +3,21 @@ library angular.zone;
|
||||||
import 'dart:async' as async;
|
import 'dart:async' as async;
|
||||||
import 'package:stack_trace/stack_trace.dart' show Chain;
|
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 {
|
class VmTurnZone {
|
||||||
Function _onTurnStart;
|
Function _onTurnStart;
|
||||||
Function _onTurnDone;
|
Function _onTurnDone;
|
||||||
|
@ -14,12 +29,29 @@ class VmTurnZone {
|
||||||
|
|
||||||
int _nestedRunCounter;
|
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}) {
|
VmTurnZone({bool enableLongStackTrace}) {
|
||||||
_nestedRunCounter = 0;
|
_nestedRunCounter = 0;
|
||||||
_outerZone = async.Zone.current;
|
_outerZone = async.Zone.current;
|
||||||
_innerZone = _createInnerZoneWithErrorHandling(enableLongStackTrace);
|
_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}) {
|
initCallbacks({Function onTurnStart, Function onTurnDone, Function onScheduleMicrotask, Function onErrorHandler}) {
|
||||||
this._onTurnStart = onTurnStart;
|
this._onTurnStart = onTurnStart;
|
||||||
this._onTurnDone = onTurnDone;
|
this._onTurnDone = onTurnDone;
|
||||||
|
@ -27,11 +59,45 @@ class VmTurnZone {
|
||||||
this._onErrorHandler = onErrorHandler;
|
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 = <ref to the application zone>;
|
||||||
|
*
|
||||||
|
* void functionCalledFromJS() {
|
||||||
|
* zone.run(() {
|
||||||
|
* // auto-digest will run after this function is called from JS
|
||||||
|
* });
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
dynamic run(fn()) => _innerZone.run(fn);
|
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);
|
dynamic runOutsideAngular(fn()) => _outerZone.run(fn);
|
||||||
|
|
||||||
|
|
||||||
async.Zone _createInnerZoneWithErrorHandling(bool enableLongStackTrace) {
|
async.Zone _createInnerZoneWithErrorHandling(bool enableLongStackTrace) {
|
||||||
if (enableLongStackTrace) {
|
if (enableLongStackTrace) {
|
||||||
return Chain.capture(() {
|
return Chain.capture(() {
|
||||||
|
|
|
@ -1,6 +1,17 @@
|
||||||
import {List, ListWrapper, StringMapWrapper} from 'angular2/src/facade/collection';
|
import {List, ListWrapper, StringMapWrapper} from 'angular2/src/facade/collection';
|
||||||
import {normalizeBlank, isPresent, global} from 'angular2/src/facade/lang';
|
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 {
|
export class VmTurnZone {
|
||||||
_outerZone;
|
_outerZone;
|
||||||
_innerZone;
|
_innerZone;
|
||||||
|
@ -11,6 +22,15 @@ export class VmTurnZone {
|
||||||
|
|
||||||
_nestedRunCounter:number;
|
_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}) {
|
constructor({enableLongStackTrace}) {
|
||||||
this._nestedRunCounter = 0;
|
this._nestedRunCounter = 0;
|
||||||
this._onTurnStart = null;
|
this._onTurnStart = null;
|
||||||
|
@ -21,16 +41,54 @@ export class VmTurnZone {
|
||||||
this._innerZone = this._createInnerZone(this._outerZone, enableLongStackTrace);
|
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} = {}) {
|
initCallbacks({onTurnStart, onTurnDone, onScheduleMicrotask, onErrorHandler} = {}) {
|
||||||
this._onTurnStart = normalizeBlank(onTurnStart);
|
this._onTurnStart = normalizeBlank(onTurnStart);
|
||||||
this._onTurnDone = normalizeBlank(onTurnDone);
|
this._onTurnDone = normalizeBlank(onTurnDone);
|
||||||
this._onErrorHandler = normalizeBlank(onErrorHandler);
|
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 = <ref to the application zone>;
|
||||||
|
*
|
||||||
|
* zone.run(() => {
|
||||||
|
* // auto-digest will run after this function is called from JS
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
run(fn) {
|
run(fn) {
|
||||||
return this._innerZone.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 = <ref to the application zone>;
|
||||||
|
*
|
||||||
|
* zone.runOusideAngular(() => {
|
||||||
|
* element.onClick(() => {
|
||||||
|
* // Clicking on the element would not trigger the change detection
|
||||||
|
* });
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
runOutsideAngular(fn) {
|
runOutsideAngular(fn) {
|
||||||
return this._outerZone.run(fn);
|
return this._outerZone.run(fn);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue