Skip to content

Commit 0e28297

Browse files
committed
feat(zone): add "on event done" zone hook
1 parent 1eebcea commit 0e28297

File tree

5 files changed

+207
-89
lines changed

5 files changed

+207
-89
lines changed

modules/angular2/src/core/application.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ function _createNgZone(givenReporter: Function): NgZone {
146146
var reporter = isPresent(givenReporter) ? givenReporter : defaultErrorReporter;
147147

148148
var zone = new NgZone({enableLongStackTrace: assertionsEnabled()});
149-
zone.initCallbacks({onErrorHandler: reporter});
149+
zone.overrideOnErrorHandler(reporter);
150150
return zone;
151151
}
152152

modules/angular2/src/core/life_cycle/life_cycle.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,8 @@ export class LifeCycle {
5757
this._changeDetector = changeDetector;
5858
}
5959

60-
zone.initCallbacks({onErrorHandler: this._errorHandler, onTurnDone: () => this.tick()});
60+
zone.overrideOnErrorHandler(this._errorHandler);
61+
zone.overrideOnTurnDone(() => this.tick());
6162
}
6263

6364
/**

modules/angular2/src/core/zone/ng_zone.dart

Lines changed: 44 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ library angular.zone;
33
import 'dart:async';
44
import 'package:stack_trace/stack_trace.dart' show Chain;
55

6+
typedef void ZeroArgFunction();
7+
typedef void ErrorHandlingFn(error, stackTrace);
8+
69
/**
710
* A `Zone` wrapper that lets you schedule tasks after its private microtask queue is exhausted but
811
* before the next "VM turn", i.e. event loop iteration.
@@ -19,9 +22,10 @@ import 'package:stack_trace/stack_trace.dart' show Chain;
1922
* instantiated. The default `onTurnDone` runs the Angular change detection.
2023
*/
2124
class NgZone {
22-
Function _onTurnStart;
23-
Function _onTurnDone;
24-
Function _onErrorHandler;
25+
ZeroArgFunction _onTurnStart;
26+
ZeroArgFunction _onTurnDone;
27+
ZeroArgFunction _onEventDone;
28+
ErrorHandlingFn _onErrorHandler;
2529

2630
// Code executed in _mountZone does not trigger the onTurnDone.
2731
Zone _mountZone;
@@ -65,21 +69,40 @@ class NgZone {
6569
}
6670

6771
/**
68-
* Initializes the zone hooks.
69-
*
70-
* The given error handler should re-throw the passed exception. Otherwise, exceptions will not
71-
* propagate outside of the [NgZone] and can alter the application execution flow.
72-
* Not re-throwing could be used to help testing the code or advanced use cases.
72+
* Sets the zone hook that is called just before Angular event turn starts.
73+
* It is called once per browser event.
74+
*/
75+
void overrideOnTurnStart(ZeroArgFunction onTurnStartFn) {
76+
this._onTurnStart = onTurnStartFn;
77+
}
78+
79+
/**
80+
* Sets the zone hook that is called immediately after Angular processes
81+
* all pending microtasks.
82+
*/
83+
void overrideOnTurnDone(ZeroArgFunction onTurnDoneFn) {
84+
this._onTurnDone = onTurnDoneFn;
85+
}
86+
87+
/**
88+
* Sets the zone hook that is called immediately after the last turn in the
89+
* current event completes. At this point Angular will no longer attempt to
90+
* sync the UI. Any changes to the data model will not be reflected in the
91+
* DOM. {@link onEventDoneFn} is executed outside Angular zone.
7392
*
74-
* @param {Function} onTurnStart called before code executes in the inner zone for each VM turn
75-
* @param {Function} onTurnDone called at the end of a VM turn if code has executed in the inner zone
76-
* @param {Function} onErrorHandler called when an exception is thrown by a macro or micro task
93+
* This hook is useful for validating application state (e.g. in a test).
7794
*/
78-
void initCallbacks(
79-
{Function onTurnStart, Function onTurnDone, Function onErrorHandler}) {
80-
_onTurnStart = onTurnStart;
81-
_onTurnDone = onTurnDone;
82-
_onErrorHandler = onErrorHandler;
95+
void overrideOnEventDone(ZeroArgFunction onEventDoneFn) {
96+
this._onEventDone = onEventDoneFn;
97+
}
98+
99+
/**
100+
* Sets the zone hook that is called when an error is uncaught in the
101+
* Angular zone. The first argument is the error. The second argument is
102+
* the stack trace.
103+
*/
104+
void overrideOnErrorHandler(ErrorHandlingFn errorHandlingFn) {
105+
this._onErrorHandler = errorHandlingFn;
83106
}
84107

85108
/**
@@ -150,7 +173,11 @@ class NgZone {
150173
// Trigger onTurnDone at the end of a turn if _innerZone has executed some code
151174
try {
152175
_inVmTurnDone = true;
153-
parent.run(_innerZone, _onTurnDone);
176+
parent.run(_innerZone, _onTurnDone);
177+
178+
if (_pendingMicrotasks == 0 && _onEventDone != null) {
179+
runOutsideAngular(_onEventDone);
180+
}
154181
} finally {
155182
_inVmTurnDone = false;
156183
_hasExecutedCodeInInnerZone = false;

modules/angular2/src/core/zone/ng_zone.ts

Lines changed: 37 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ export class NgZone {
2323

2424
_onTurnStart: () => void;
2525
_onTurnDone: () => void;
26+
_onEventDone: () => void;
2627
_onErrorHandler: (error, stack) => void;
2728

2829
// Number of microtasks pending from _innerZone (& descendants)
@@ -53,6 +54,7 @@ export class NgZone {
5354
constructor({enableLongStackTrace}) {
5455
this._onTurnStart = null;
5556
this._onTurnDone = null;
57+
this._onEventDone = null;
5658
this._onErrorHandler = null;
5759

5860
this._pendingMicrotasks = 0;
@@ -70,22 +72,40 @@ export class NgZone {
7072
}
7173

7274
/**
73-
* Initializes the zone hooks.
75+
* Sets the zone hook that is called just before Angular event turn starts.
76+
* It is called once per browser event.
77+
*/
78+
overrideOnTurnStart(onTurnStartFn: Function): void {
79+
this._onTurnStart = normalizeBlank(onTurnStartFn);
80+
}
81+
82+
/**
83+
* Sets the zone hook that is called immediately after Angular processes
84+
* all pending microtasks.
85+
*/
86+
overrideOnTurnDone(onTurnDoneFn: Function): void {
87+
this._onTurnDone = normalizeBlank(onTurnDoneFn);
88+
}
89+
90+
/**
91+
* Sets the zone hook that is called immediately after the last turn in the
92+
* current event completes. At this point Angular will no longer attempt to
93+
* sync the UI. Any changes to the data model will not be reflected in the
94+
* DOM. {@link onEventDoneFn} is executed outside Angular zone.
7495
*
75-
* @param {() => void} onTurnStart called before code executes in the inner zone for each VM turn
76-
* @param {() => void} onTurnDone called at the end of a VM turn if code has executed in the inner
77-
* zone
78-
* @param {(error, stack) => void} onErrorHandler called when an exception is thrown by a macro or
79-
* micro task
96+
* This hook is useful for validating application state (e.g. in a test).
97+
*/
98+
overrideOnEventDone(onEventDoneFn: Function): void {
99+
this._onEventDone = normalizeBlank(onEventDoneFn);
100+
}
101+
102+
/**
103+
* Sets the zone hook that is called when an error is uncaught in the
104+
* Angular zone. The first argument is the error. The second argument is
105+
* the stack trace.
80106
*/
81-
initCallbacks({onTurnStart, onTurnDone, onErrorHandler}: {
82-
onTurnStart?: /*() => void*/ Function,
83-
onTurnDone?: /*() => void*/ Function,
84-
onErrorHandler?: /*(error, stack) => void*/ Function
85-
} = {}) {
86-
this._onTurnStart = normalizeBlank(onTurnStart);
87-
this._onTurnDone = normalizeBlank(onTurnDone);
88-
this._onErrorHandler = normalizeBlank(onErrorHandler);
107+
overrideOnErrorHandler(errorHandlingFn: Function): void {
108+
this._onErrorHandler = normalizeBlank(errorHandlingFn);
89109
}
90110

91111
/**
@@ -172,6 +192,9 @@ export class NgZone {
172192
try {
173193
this._inVmTurnDone = true;
174194
parentRun.call(ngZone._innerZone, ngZone._onTurnDone);
195+
if (ngZone._pendingMicrotasks === 0 && isPresent(ngZone._onEventDone)) {
196+
ngZone.runOutsideAngular(ngZone._onEventDone);
197+
}
175198
} finally {
176199
this._inVmTurnDone = false;
177200
ngZone._hasExecutedCodeInInnerZone = false;

0 commit comments

Comments
 (0)