| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495 |
- 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 waiting = false
- var flushing = false
- var internalQueueDepleted = false
- /**
- * Reset the batcher's state.
- */
- function reset () {
- queue = []
- userQueue = []
- has = {}
- waiting = flushing = internalQueueDepleted = false
- }
- /**
- * Flush both queues and run the jobs.
- */
- function flush () {
- flushing = true
- run(queue)
- internalQueueDepleted = true
- 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) {
- var id = job.id
- if (!id || !has[id] || flushing) {
- if (!has[id]) {
- has[id] = 1
- } else {
- has[id]++
- // detect possible infinite update loops
- if (has[id] > config._maxUpdateCount) {
- _.warn(
- 'You may have an infinite update loop for the ' +
- 'watcher with expression: "' + job.expression + '".'
- )
- return
- }
- }
- // 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 && internalQueueDepleted) {
- job.run()
- return
- }
- ;(job.user ? userQueue : queue).push(job)
- if (!waiting) {
- waiting = true
- _.nextTick(flush)
- }
- }
- }
|