-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbatcher.js
80 lines (71 loc) · 1.64 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
var _ = require('./util')
// 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 waiting = false
var flushing = false
/**
* Reset the batcher's state.
*/
function reset () {
queue = []
userQueue = []
has = {}
waiting = false
flushing = false
}
/**
* Flush both queues and run the jobs.
*/
function flush () {
flushing = true
run(queue)
run(userQueue)
reset()
}
/**
* Run the jobs in a single queue.
*
* @param {Array} queue
*/
function run (queue) {
// do not cache length because more jobs might be pushed
// as we run existing jobs
for (var i = 0; i < queue.length; i++) {
queue[i].run()
}
}
/**
* Push a job into the job queue.
* Jobs with duplicate IDs will be skipped unless it's
* pushed when the queue is being flushed.
*
* @param {Object} job
* properties:
* - {String|Number} id
* - {Function} run
*/
exports.push = function (job) {
if (!job.id || !has[job.id] || flushing) {
// A user watcher callback could trigger another
// directive update during the flushing; at that time
// the directive queue would already have been run, so
// we call that update immediately as it is pushed.
if (flushing && !job.user) {
job.run()
return
}
;(job.user ? userQueue : queue).push(job)
has[job.id] = job
if (!waiting) {
waiting = true
_.nextTick(flush)
}
}
}