github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/public/libs/vue-1.0.24/src/batcher.js (about) 1 import config from './config' 2 import { 3 warn, 4 nextTick, 5 devtools 6 } from './util/index' 7 8 // we have two separate queues: one for directive updates 9 // and one for user watcher registered via $watch(). 10 // we want to guarantee directive updates to be called 11 // before user watchers so that when user watchers are 12 // triggered, the DOM would have already been in updated 13 // state. 14 15 var queue = [] 16 var userQueue = [] 17 var has = {} 18 var circular = {} 19 var waiting = false 20 21 /** 22 * Reset the batcher's state. 23 */ 24 25 function resetBatcherState () { 26 queue.length = 0 27 userQueue.length = 0 28 has = {} 29 circular = {} 30 waiting = false 31 } 32 33 /** 34 * Flush both queues and run the watchers. 35 */ 36 37 function flushBatcherQueue () { 38 runBatcherQueue(queue) 39 runBatcherQueue(userQueue) 40 // user watchers triggered more watchers, 41 // keep flushing until it depletes 42 if (queue.length) { 43 return flushBatcherQueue() 44 } 45 // dev tool hook 46 /* istanbul ignore if */ 47 if (devtools && config.devtools) { 48 devtools.emit('flush') 49 } 50 resetBatcherState() 51 } 52 53 /** 54 * Run the watchers in a single queue. 55 * 56 * @param {Array} queue 57 */ 58 59 function runBatcherQueue (queue) { 60 // do not cache length because more watchers might be pushed 61 // as we run existing watchers 62 for (let i = 0; i < queue.length; i++) { 63 var watcher = queue[i] 64 var id = watcher.id 65 has[id] = null 66 watcher.run() 67 // in dev build, check and stop circular updates. 68 if (process.env.NODE_ENV !== 'production' && has[id] != null) { 69 circular[id] = (circular[id] || 0) + 1 70 if (circular[id] > config._maxUpdateCount) { 71 warn( 72 'You may have an infinite update loop for watcher ' + 73 'with expression "' + watcher.expression + '"', 74 watcher.vm 75 ) 76 break 77 } 78 } 79 } 80 queue.length = 0 81 } 82 83 /** 84 * Push a watcher into the watcher queue. 85 * Jobs with duplicate IDs will be skipped unless it's 86 * pushed when the queue is being flushed. 87 * 88 * @param {Watcher} watcher 89 * properties: 90 * - {Number} id 91 * - {Function} run 92 */ 93 94 export function pushWatcher (watcher) { 95 const id = watcher.id 96 if (has[id] == null) { 97 // push watcher into appropriate queue 98 const q = watcher.user 99 ? userQueue 100 : queue 101 has[id] = q.length 102 q.push(watcher) 103 // queue the flush 104 if (!waiting) { 105 waiting = true 106 nextTick(flushBatcherQueue) 107 } 108 } 109 }