Commit e32cd162 authored by Luke Melia's avatar Luke Melia

Add callbacks to a queue and schedule a task to flush the queue instead of...

Add callbacks to a queue and schedule a task to flush the queue instead of scheduling an async task for every callback, .

Previously, we were using setImmediate when it exists. However, due to #115,
we would like to stay away from it for IE 10 and we don't really need it for
node since this new approach does not result in deeply nested `nextTick`s.
(See #66 for background on the node issue.) It turns out that these are the
only two supported environments that setImmediate is implemented.
parent dd67073e
var browserGlobal = (typeof window !== 'undefined') ? window : {};
var BrowserMutationObserver = browserGlobal.MutationObserver || browserGlobal.WebKitMutationObserver;
var async;
var local = (typeof global !== 'undefined') ? global : this;
// old node
// node
function useNextTick() {
return function(callback, arg) {
process.nextTick(function() {
callback(arg);
});
};
}
// node >= 0.10.x
function useSetImmediate() {
return function(callback, arg) {
/* global setImmediate */
setImmediate(function(){
callback(arg);
});
return function() {
process.nextTick(flush);
};
}
function useMutationObserver() {
var queue = [];
var observer = new BrowserMutationObserver(function() {
var toProcess = queue.slice();
queue = [];
toProcess.forEach(function(tuple) {
var callback = tuple[0], arg= tuple[1];
callback(arg);
});
});
var observer = new BrowserMutationObserver(flush);
var element = document.createElement('div');
observer.observe(element, { attributes: true });
......@@ -44,28 +20,46 @@ function useMutationObserver() {
observer = null;
}, false);
return function(callback, arg) {
queue.push([callback, arg]);
return function() {
element.setAttribute('drainQueue', 'drainQueue');
};
}
function useSetTimeout() {
return function(callback, arg) {
local.setTimeout(function() {
callback(arg);
}, 1);
return function() {
local.setTimeout(flush, 1);
};
}
if (typeof setImmediate === 'function') {
async = useSetImmediate();
} else if (typeof process !== 'undefined' && {}.toString.call(process) === '[object process]') {
async = useNextTick();
var queue = [];
function flush() {
for (var i = 0; i < queue.length; i++) {
var tuple = queue[i];
var callback = tuple[0], arg = tuple[1];
callback(arg);
}
queue = [];
}
var scheduleFlush;
// Decide what async method to use to triggering processing of queued callbacks:
if (typeof process !== 'undefined' && {}.toString.call(process) === '[object process]') {
scheduleFlush = useNextTick();
} else if (BrowserMutationObserver) {
async = useMutationObserver();
scheduleFlush = useMutationObserver();
} else {
async = useSetTimeout();
scheduleFlush = useSetTimeout();
}
function async(callback, arg) {
var length = queue.push([callback, arg]);
if (length === 1) {
// If length is 1, that means that we need to schedule an async flush.
// If additional callbacks are queued before the queue is flushed, they
// will be processed by this flush that we are scheduling.
scheduleFlush();
}
}
export { async };
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment