Parcourir la source

improve nextTick

Evan You il y a 11 ans
Parent
commit
c9b425dc23
1 fichiers modifiés avec 35 ajouts et 40 suppressions
  1. 35 40
      src/util/env.js

+ 35 - 40
src/util/env.js

@@ -20,55 +20,50 @@ var inBrowser = exports.inBrowser =
 /**
  * Defer a task to execute it asynchronously. Ideally this
  * should be executed as a microtask, so we leverage
- * MutationObserver if it's available.
- * 
- * If the user has included a setImmediate polyfill, we can
- * also use that. In Node we actually prefer setImmediate to
- * process.nextTick so we don't block the I/O.
- * 
- * Finally, fallback to setTimeout(0) if nothing else works.
+ * MutationObserver if it's available, and fallback to
+ * setTimeout(0).
  *
  * @param {Function} cb
  * @param {Object} ctx
  */
 
-var defer
-/* istanbul ignore if */
-if (typeof MutationObserver !== 'undefined') {
-  defer = deferFromMutationObserver(MutationObserver)
-} else
-/* istanbul ignore if */
-if (typeof WebkitMutationObserver !== 'undefined') {
-  defer = deferFromMutationObserver(WebkitMutationObserver)
-} else {
-  defer = setTimeout
-}
-
-/* istanbul ignore next */
-function deferFromMutationObserver (Observer) {
-  var queue = []
-  var node = document.createTextNode('0')
-  var i = 0
-  new Observer(function () {
-    var l = queue.length
-    for (var i = 0; i < l; i++) {
-      queue[i]()
+exports.nextTick = (function () {
+  var callbacks = []
+  var pending = false
+  var timerFunc
+  function handle () {
+    pending = false
+    var copies = callbacks.slice(0)
+    callbacks = []
+    for (var i = 0; i < copies.length; i++) {
+      copies[i]()
     }
-    queue = queue.slice(l)
-  }).observe(node, { characterData: true })
-  return function mutationObserverDefer (cb) {
-    queue.push(cb)
-    node.nodeValue = (i = ++i % 2)
   }
-}
-
-exports.nextTick = function (cb, ctx) {
-  if (ctx) {
-    defer(function () { cb.call(ctx) }, 0)
+  /* istanbul ignore if */
+  if (typeof MutationObserver !== 'undefined') {
+    var counter = 1
+    var observer = new MutationObserver(handle)
+    var textNode = document.createTextNode(counter)
+    observer.observe(textNode, {
+      characterData: true
+    })
+    timerFunc = function () {
+      counter = (counter + 1) % 2
+      textNode.data = counter
+    }
   } else {
-    defer(cb, 0)
+    timerFunc = setTimeout
+  }
+  return function (cb, ctx) {
+    var func = ctx
+      ? function () { cb.call(ctx) }
+      : cb
+    callbacks.push(func)
+    if (pending) return
+    pending = true
+    timerFunc(handle, 0)
   }
-}
+})()
 
 /**
  * Detect if we are in IE9...