-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbatcher.js
98 lines (89 loc) · 2.3 KB
/
batcher.js
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
var _ = require('./util')
var config = require('./config')
// we have two separate queues: one for directive updates
// and one for user watcher registered via $watch().
// we want to guarantee directive updates to be called
// before user watchers so that when user watchers are
// triggered, the DOM would have already been in updated
// state.
var queue = []
var userQueue = []
var has = {}
var circular = {}
var waiting = false
var internalQueueDepleted = false
/**
* Reset the batcher's state.
*/
function resetBatcherState () {
queue = []
userQueue = []
has = {}
circular = {}
waiting = internalQueueDepleted = false
}
/**
* Flush both queues and run the watchers.
*/
function flushBatcherQueue () {
runBatcherQueue(queue)
internalQueueDepleted = true
runBatcherQueue(userQueue)
resetBatcherState()
}
/**
* Run the watchers in a single queue.
*
* @param {Array} queue
*/
function runBatcherQueue (queue) {
// do not cache length because more watchers might be pushed
// as we run existing watchers
for (var i = 0; i < queue.length; i++) {
var watcher = queue[i]
var id = watcher.id
has[id] = null
watcher.run()
// in dev build, check and stop circular updates.
if (process.env.NODE_ENV !== 'production' && has[id] != null) {
circular[id] = (circular[id] || 0) + 1
if (circular[id] > config._maxUpdateCount) {
queue.splice(has[id], 1)
_.warn(
'You may have an infinite update loop for watcher ' +
'with expression: ' + watcher.expression
)
}
}
}
}
/**
* Push a watcher into the watcher queue.
* Jobs with duplicate IDs will be skipped unless it's
* pushed when the queue is being flushed.
*
* @param {Watcher} watcher
* properties:
* - {Number} id
* - {Function} run
*/
exports.push = function (watcher) {
var id = watcher.id
if (has[id] == null) {
// if an internal watcher is pushed, but the internal
// queue is already depleted, we run it immediately.
if (internalQueueDepleted && !watcher.user) {
watcher.run()
return
}
// push watcher into appropriate queue
var q = watcher.user ? userQueue : queue
has[id] = q.length
q.push(watcher)
// queue the flush
if (!waiting) {
waiting = true
_.nextTick(flushBatcherQueue)
}
}
}