1
1
part of angular.core_internal;
2
2
3
+ /**
4
+ * Handles an [NgZone] onTurnDone event.
5
+ */
3
6
typedef void ZoneOnTurn ();
7
+
8
+ /**
9
+ * Handles an [NgZone] onError event.
10
+ */
4
11
typedef void ZoneOnError (dynamic error, dynamic stacktrace,
5
12
LongStackTrace longStacktrace);
6
13
7
14
/**
8
- * Contains the locations of runAsync calls across VM turns.
15
+ * Contains the locations of async calls across VM turns.
9
16
*/
10
17
class LongStackTrace {
11
18
final String reason;
@@ -26,25 +33,44 @@ class LongStackTrace {
26
33
}
27
34
28
35
/**
29
- * A better zone API which implements onTurnDone.
36
+ * A [Zone] wrapper that lets you schedule tasks after its private microtask
37
+ * queue is exhausted but before the next "turn", i.e. event loop iteration.
38
+ * This lets you freely schedule microtasks that prepare data, and set an
39
+ * [onTurnDone] handler that will consume that data after it's ready but before
40
+ * the browser has a chance to re-render.
41
+ * The wrapper maintains an "inner" and "outer" [Zone] and a private queue of
42
+ * all the microtasks scheduled on the inner [Zone] .
43
+ *
44
+ * In a typical app, [ngDynamicApp] or [ngStaticApp] will create a singleton
45
+ * [NgZone] whose outer [Zone] is the root [Zone] and whose default [onTurnDone]
46
+ * runs the Angular digest. A component may want to inject this singleton if it
47
+ * needs to run code _outside_ the Angular digest.
30
48
*/
31
49
class NgZone {
32
- final async . Zone _outerZone = async . Zone .current;
33
- async .Zone _zone ;
50
+ /// an "outer" [ Zone] , which is the one that created this.
51
+ async .Zone _outerZone ;
34
52
53
+ /// an "inner" [Zone] , which is a child of the outer [Zone] .
54
+ async .Zone _innerZone;
55
+
56
+ /**
57
+ * Associates with this
58
+ *
59
+ * Defaults [onError] to forward errors to the outer [Zone] .
60
+ * Defaults [onTurnDone] to a no-op.
61
+ */
35
62
NgZone () {
36
- _zone = _outerZone.fork (specification: new async .ZoneSpecification (
63
+ _outerZone = async .Zone .current;
64
+ _innerZone = _outerZone.fork (specification: new async .ZoneSpecification (
37
65
run: _onRun,
38
66
runUnary: _onRunUnary,
39
67
scheduleMicrotask: _onScheduleMicrotask,
40
68
handleUncaughtError: _uncaughtError
41
69
));
42
- // Prevent silently ignoring uncaught exceptions by forwarding such
43
- // exceptions to the outer zone by default.
44
- onError = (e, s, ls) => _outerZone.handleUncaughtError (e, s);
70
+ onError = _defaultOnError;
71
+ onTurnDone = _defaultOnTurnDone;
45
72
}
46
73
47
-
48
74
List _asyncQueue = [];
49
75
bool _errorThrownFromOnRun = false ;
50
76
@@ -107,21 +133,27 @@ class NgZone {
107
133
int _runningInTurn = 0 ;
108
134
109
135
/**
110
- * A function called with any errors from the zone.
136
+ * Called with any errors from the inner zone.
111
137
*/
112
- var onError = (e, s, ls) => print ( '$ e \n $ s \n $ ls ' ) ;
138
+ ZoneOnError onError;
113
139
114
- /**
115
- * A function that is called at the end of each VM turn in which the
116
- * in-zone code or any runAsync callbacks were run.
117
- */
118
- var onTurnDone = () => null ; // Type was ZoneOnTurn: dartbug 13519
140
+ /// Prevent silently ignoring uncaught exceptions by forwarding such exceptions to the outer zone.
141
+ void _defaultOnError (dynamic e, dynamic s, LongStackTrace ls) =>
142
+ _outerZone.handleUncaughtError (e, s);
119
143
120
144
/**
121
- * A function that is called when uncaught errors are thrown inside the zone.
145
+ * Called at the end of each VM turn in which inner zone code runs.
146
+ * "At the end" means after the private microtask queue of the inner zone is
147
+ * exhausted but before the next VM turn. Notes
148
+ * - This won't wait for microtasks scheduled in zones other than the inner
149
+ * zone, e.g. those scheduled with [runOutsideAngular] .
150
+ * - [onTurnDone] runs repeatedly until it fails to schedule any more
151
+ * microtasks, so you usually don't want it to schedule any. For example,
152
+ * if its first line of code is `new Future.value()` , the turn will _never_
153
+ * end.
122
154
*/
123
- // var onError = (dynamic e, dynamic s, LongStackTrace ls) => print('EXCEPTION: $e\n$s\n$ls') ;
124
- // Type was ZoneOnError: dartbug 13519
155
+ ZoneOnTurn onTurnDone ;
156
+ void _defaultOnTurnDone () => null ;
125
157
126
158
LongStackTrace _longStacktrace = null ;
127
159
@@ -140,15 +172,14 @@ class NgZone {
140
172
}
141
173
142
174
/**
143
- * Runs the provided function in the zone. Any runAsync calls (e.g. futures)
144
- * will also be run in this zone.
145
- *
146
- * Returns the return value of body.
175
+ * Runs [body] in the inner zone and returns whatever it returns.
147
176
*/
148
- dynamic run (body ()) => _zone .run (body);
177
+ dynamic run (body ()) => _innerZone .run (body);
149
178
150
179
/**
151
- * Allows one to escape the auto-digest mechanism of Angular.
180
+ * Runs [body] in the outer zone and returns whatever it returns.
181
+ * In a typical app where the inner zone is the Angular zone, this allows
182
+ * one to escape Angular's auto-digest mechanism.
152
183
*
153
184
* myFunction(NgZone zone, Element element) {
154
185
* element.onClick.listen(() {
@@ -163,10 +194,19 @@ class NgZone {
163
194
*/
164
195
dynamic runOutsideAngular (body ()) => _outerZone.run (body);
165
196
197
+ /**
198
+ * Throws an [AssertionError] if no task is currently running in the inner
199
+ * zone. In a typical app where the inner zone is the Angular zone, this can
200
+ * be used to assert that the digest will indeed run at the end of the current
201
+ * turn.
202
+ */
166
203
void assertInTurn () {
167
204
assert (_runningInTurn > 0 || _inFinishTurn);
168
205
}
169
206
207
+ /**
208
+ * Same as [assertInTurn] .
209
+ */
170
210
void assertInZone () {
171
211
assertInTurn ();
172
212
}
0 commit comments