@@ -11,6 +11,24 @@ function Batcher () {
11
11
12
12
var p = Batcher . prototype
13
13
14
+ /**
15
+ * Reset the batcher's state.
16
+ */
17
+
18
+ p . reset = function ( ) {
19
+ this . has = { }
20
+ // we have two separate queues: one for directive updates
21
+ // and one for user watcher registered via $watch().
22
+ // we want to guarantee directive updates to be called
23
+ // before user watchers so that when user watchers are
24
+ // triggered, the DOM would have already been in updated
25
+ // state.
26
+ this . queue = [ ]
27
+ this . userQueue = [ ]
28
+ this . waiting = false
29
+ this . flushing = false
30
+ }
31
+
14
32
/**
15
33
* Push a job into the job queue.
16
34
* Jobs with duplicate IDs will be skipped unless it's
@@ -24,7 +42,18 @@ var p = Batcher.prototype
24
42
25
43
p . push = function ( job ) {
26
44
if ( ! job . id || ! this . has [ job . id ] || this . flushing ) {
27
- this . queue . push ( job )
45
+ // A user watcher callback could trigger another
46
+ // directive update during the flushing; at that time
47
+ // the directive queue would already have been run, so
48
+ // we call that update immediately as it is pushed.
49
+ if ( this . flushing && ! job . user ) {
50
+ job . run ( )
51
+ return
52
+ }
53
+ var queue = job . user
54
+ ? this . userQueue
55
+ : this . queue
56
+ queue . push ( job )
28
57
this . has [ job . id ] = job
29
58
if ( ! this . waiting ) {
30
59
this . waiting = true
@@ -34,32 +63,31 @@ p.push = function (job) {
34
63
}
35
64
36
65
/**
37
- * Flush the queue and run the jobs.
38
- * Will call a preFlush hook if has one.
66
+ * Flush both queues and run the jobs.
39
67
*/
40
68
41
69
p . flush = function ( ) {
42
70
this . flushing = true
43
- // do not cache length because more jobs might be pushed
44
- // as we run existing jobs
45
- for ( var i = 0 ; i < this . queue . length ; i ++ ) {
46
- var job = this . queue [ i ]
47
- if ( ! job . cancelled ) {
48
- job . run ( )
49
- }
50
- }
71
+ this . run ( this . queue )
72
+ this . run ( this . userQueue )
51
73
this . reset ( )
52
74
}
53
75
54
76
/**
55
- * Reset the batcher's state.
77
+ * Run the jobs in a single queue.
78
+ *
79
+ * @param {Array } queue
56
80
*/
57
81
58
- p . reset = function ( ) {
59
- this . has = { }
60
- this . queue = [ ]
61
- this . waiting = false
62
- this . flushing = false
82
+ p . run = function ( queue ) {
83
+ // do not cache length because more jobs might be pushed
84
+ // as we run existing jobs
85
+ for ( var i = 0 ; i < queue . length ; i ++ ) {
86
+ var job = queue [ i ]
87
+ if ( ! job . cancelled ) {
88
+ job . run ( )
89
+ }
90
+ }
63
91
}
64
92
65
93
module . exports = Batcher
0 commit comments