Evan You 12 лет назад
Родитель
Сommit
ed688dc122
2 измененных файлов с 91 добавлено и 0 удалено
  1. 77 0
      src/batcher.js
  2. 14 0
      src/util.js

+ 77 - 0
src/batcher.js

@@ -0,0 +1,77 @@
+var _ = require('./util')
+
+/**
+ * The Batcher maintains a job queue to be executed
+ * async on the next event loop.
+ */
+
+function Batcher () {
+  this._preFlush = null
+  this.reset()
+}
+
+var p = Batcher.prototype
+
+/**
+ * Push a job into the job queue.
+ * Jobs with duplicate IDs will be skipped, however we can
+ * use the `override` option to override existing jobs.
+ *
+ * @param {Object} job
+ *   properties:
+ *   - {String|Number} id
+ *   - {Boolean}       override
+ *   - {Function}      execute
+ */
+
+p.push = function (job) {
+  if (!job.id || !this.has[job.id]) {
+    this.queue.push(job)
+    this.has[job.id] = job
+    if (!this.waiting) {
+      this.waiting = true
+      var self = this
+      _.nextTick(function () {
+        self.flush()
+      })
+    }
+  } else if (job.override) {
+    var oldJob = this.has[job.id]
+    oldJob.cancelled = true
+    this.queue.push(job)
+    this.has[job.id] = job
+  }
+}
+
+/**
+ * Flush the queue and run the jobs.
+ * Will call a preFlush hook if has one.
+ */
+
+p.flush = function () {
+  // before flush hook
+  if (this._preFlush) {
+    this._preFlush()
+  }
+  // do not cache length because more jobs might be pushed
+  // as we execute existing jobs
+  for (var i = 0; i < this.queue.length; i++) {
+    var job = this.queue[i]
+    if (!job.cancelled) {
+      job.execute()
+    }
+  }
+  this.reset()
+}
+
+/**
+ * Reset the batcher's state.
+ */
+
+p.reset = function () {
+  this.has = {}
+  this.queue = []
+  this.waiting = false
+}
+
+module.exports = Batcher

+ 14 - 0
src/util.js

@@ -1,5 +1,19 @@
 var config = require('./config')
 var slice = [].slice
+var defer =
+  win.requestAnimationFrame ||
+  win.webkitRequestAnimationFrame ||
+  win.setTimeout
+
+/**
+ * Defer a task to the start of the next event loop
+ *
+ * @param {Function} fn
+ */
+
+exports.nextTick = function (fn) {
+  return defer(fn, 0)
+}
 
 /**
  * Convert an Array-like object to a real Array.