forked from Urigo/angular-meteor
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathzone_utils.ts
115 lines (94 loc) · 2.65 KB
/
zone_utils.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
'use strict';
import isFunction from 'lodash/isFunction';
import functions from 'lodash/functions';
/**
* Contains a set of methods to schedule Zone runs.
* Supposed to be used mostly in @MeteorReactive to patch
* Meteor methods' callbacks.
* After patching, callbacks will be run in the global zone
* (i.e. outside of Angular 2), at the same time,
* a Angular 2 zone run will be scheduled in order to
* initiate UI update. In order to reduce number of
* UI updates caused by the callbacks near the same time,
* zone runs are debounced.
*/
import {MeteorCallbacks, gZone, check, noop} from './utils';
export class ZoneRunScheduler {
private _zoneTasks = new Map<Zone, Task>();
private _onRunCbs = new Map<Zone, Function[]>();
zoneRun(zone: Zone): Function {
return () => {
zone.run(noop);
this._runAfterRunCbs(zone);
this._zoneTasks.delete(zone);
};
}
runZones() {
this._zoneTasks.forEach((task, zone) => {
task.invoke();
});
}
_runAfterRunCbs(zone: Zone) {
if (this._onRunCbs.has(zone)) {
let cbs = this._onRunCbs.get(zone);
while (cbs.length !== 0) {
(cbs.pop())();
}
this._onRunCbs.delete(zone);
}
}
scheduleRun(zone: Zone) {
if (zone === gZone) {
return;
}
let runTask = this._zoneTasks.get(zone);
if (runTask) {
runTask.cancelFn(runTask);
this._zoneTasks.delete(zone);
}
runTask = gZone.scheduleMacroTask('runZones',
this.zoneRun(zone), { isPeriodic: true },
task => {
task._tHandler = setTimeout(task.invoke);
},
task => {
clearTimeout(task._tHandler);
});
this._zoneTasks.set(zone, runTask);
}
onAfterRun(zone: Zone, cb: Function) {
check(cb, Function);
if (!this._zoneTasks.has(zone)) {
cb();
return;
}
let cbs = this._onRunCbs.get(zone);
if (!cbs) {
cbs = [];
this._onRunCbs.set(zone, cbs);
}
cbs.push(cb);
}
}
export const zoneRunScheduler = new ZoneRunScheduler();
function wrapFuncInZone(zone: Zone, method: Function, context: any) {
return function(...args) {
gZone.run(() => {
method.apply(context, args);
});
zoneRunScheduler.scheduleRun(zone);
};
}
export function wrapCallbackInZone(
zone: Zone, callback: MeteorCallbacks, context: any): MeteorCallbacks {
if (isFunction(callback)) {
return wrapFuncInZone(zone, <Function>callback, context);
}
for (let fn of functions(callback)) {
callback[fn] = wrapFuncInZone(zone, callback[fn], context);
}
return callback;
}
export function scheduleMicroTask(fn: Function) {
Zone.current.scheduleMicroTask('scheduleMicrotask', fn);
}