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  }