Plato on Github
Report Home
node_modules/when/es6-shim/Promise.js
Maintainability
72.55
Lines of code
1229
Difficulty
168.69
Estimated Errors
10.16
Function weight
By Complexity
By SLOC
!function(e){"object"==typeof exports?module.exports=e():"function"==typeof define&&define.amd?define(e):"undefined"!=typeof window?window.Promise=e():"undefined"!=typeof global?global.Promise=e():"undefined"!=typeof self&&(self.Promise=e())}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ /** @license MIT License (c) copyright 2010-2014 original author or authors */ /** @author Brian Cavalier */ /** @author John Hann */ /** * ES6 global Promise shim */ var unhandledRejections = require('../lib/decorators/unhandledRejection'); var PromiseConstructor = module.exports = unhandledRejections(require('../lib/Promise')); var g = typeof global !== 'undefined' && global || typeof self !== 'undefined' && self; if(typeof g !== 'undefined' && typeof g.Promise === 'undefined') { g['Promise'] = PromiseConstructor; } },{"../lib/Promise":2,"../lib/decorators/unhandledRejection":5}],2:[function(require,module,exports){ /** @license MIT License (c) copyright 2010-2014 original author or authors */ /** @author Brian Cavalier */ /** @author John Hann */ (function(define) { 'use strict'; define(function (require) { var makePromise = require('./makePromise'); var Scheduler = require('./scheduler'); var async = require('./async'); return makePromise({ scheduler: new Scheduler(async) }); }); })(typeof define === 'function' && define.amd ? define : function (factory) { module.exports = factory(require); }); },{"./async":4,"./makePromise":6,"./scheduler":7}],3:[function(require,module,exports){ /** @license MIT License (c) copyright 2010-2014 original author or authors */ /** @author Brian Cavalier */ /** @author John Hann */ (function(define) { 'use strict'; define(function() { /** * Circular queue * @param {number} capacityPow2 power of 2 to which this queue's capacity * will be set initially. eg when capacityPow2 == 3, queue capacity * will be 8. * @constructor */ function Queue(capacityPow2) { this.head = this.tail = this.length = 0; this.buffer = new Array(1 << capacityPow2); } Queue.prototype.push = function(x) { if(this.length === this.buffer.length) { this._ensureCapacity(this.length * 2); } this.buffer[this.tail] = x; this.tail = (this.tail + 1) & (this.buffer.length - 1); ++this.length; return this.length; }; Queue.prototype.shift = function() { var x = this.buffer[this.head]; this.buffer[this.head] = void 0; this.head = (this.head + 1) & (this.buffer.length - 1); --this.length; return x; }; Queue.prototype._ensureCapacity = function(capacity) { var head = this.head; var buffer = this.buffer; var newBuffer = new Array(capacity); var i = 0; var len; if(head === 0) { len = this.length; for(; i<len; ++i) { newBuffer[i] = buffer[i]; } } else { capacity = buffer.length; len = this.tail; for(; head<capacity; ++i, ++head) { newBuffer[i] = buffer[head]; } for(head=0; head<len; ++i, ++head) { newBuffer[i] = buffer[head]; } } this.buffer = newBuffer; this.head = 0; this.tail = this.length; }; return Queue; }); }(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(); })); },{}],4:[function(require,module,exports){ /** @license MIT License (c) copyright 2010-2014 original author or authors */ /** @author Brian Cavalier */ /** @author John Hann */ (function(define) { 'use strict'; define(function(require) { // Sniff "best" async scheduling option // Prefer process.nextTick or MutationObserver, then check for // vertx and finally fall back to setTimeout /*jshint maxcomplexity:6*/ /*global process,document,setTimeout,MutationObserver,WebKitMutationObserver*/ var nextTick, MutationObs; if (typeof process !== 'undefined' && process !== null && typeof process.nextTick === 'function') { nextTick = function(f) { process.nextTick(f); }; } else if (MutationObs = (typeof MutationObserver === 'function' && MutationObserver) || (typeof WebKitMutationObserver === 'function' && WebKitMutationObserver)) { nextTick = (function (document, MutationObserver) { var scheduled; var el = document.createElement('div'); var o = new MutationObserver(run); o.observe(el, { attributes: true }); function run() { var f = scheduled; scheduled = void 0; f(); } return function (f) { scheduled = f; el.setAttribute('class', 'x'); }; }(document, MutationObs)); } else { nextTick = (function(cjsRequire) { try { // vert.x 1.x || 2.x return cjsRequire('vertx').runOnLoop || cjsRequire('vertx').runOnContext; } catch (ignore) {} // capture setTimeout to avoid being caught by fake timers // used in time based tests var capturedSetTimeout = setTimeout; return function (t) { capturedSetTimeout(t, 0); }; }(require)); } return nextTick; }); }(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(require); })); },{}],5:[function(require,module,exports){ /** @license MIT License (c) copyright 2010-2014 original author or authors */ /** @author Brian Cavalier */ /** @author John Hann */ (function(define) { 'use strict'; define(function(require) { var timer = require('../timer'); return function unhandledRejection(Promise) { var logError = noop; var logInfo = noop; if(typeof console !== 'undefined') { logError = typeof console.error !== 'undefined' ? function (e) { console.error(e); } : function (e) { console.log(e); }; logInfo = typeof console.info !== 'undefined' ? function (e) { console.info(e); } : function (e) { console.log(e); }; } Promise.onPotentiallyUnhandledRejection = function(rejection) { enqueue(report, rejection); }; Promise.onPotentiallyUnhandledRejectionHandled = function(rejection) { enqueue(unreport, rejection); }; Promise.onFatalRejection = function(rejection) { enqueue(throwit, rejection.value); }; var tasks = []; var reported = []; var running = false; function report(r) { if(!r.handled) { reported.push(r); logError('Potentially unhandled rejection [' + r.id + '] ' + formatError(r.value)); } } function unreport(r) { var i = reported.indexOf(r); if(i >= 0) { reported.splice(i, 1); logInfo('Handled previous rejection [' + r.id + '] ' + formatObject(r.value)); } } function enqueue(f, x) { tasks.push(f, x); if(!running) { running = true; running = timer.set(flush, 0); } } function flush() { running = false; while(tasks.length > 0) { tasks.shift()(tasks.shift()); } } return Promise; }; function formatError(e) { var s = typeof e === 'object' && e.stack ? e.stack : formatObject(e); return e instanceof Error ? s : s + ' (WARNING: non-Error used)'; } function formatObject(o) { var s = String(o); if(s === '[object Object]' && typeof JSON !== 'undefined') { s = tryStringify(o, s); } return s; } function tryStringify(e, defaultValue) { try { return JSON.stringify(e); } catch(e) { // Ignore. Cannot JSON.stringify e, stick with String(e) return defaultValue; } } function throwit(e) { throw e; } function noop() {} }); }(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(require); })); },{"../timer":8}],6:[function(require,module,exports){ /** @license MIT License (c) copyright 2010-2014 original author or authors */ /** @author Brian Cavalier */ /** @author John Hann */ (function(define) { 'use strict'; define(function() { return function makePromise(environment) { var tasks = environment.scheduler; var objectCreate = Object.create || function(proto) { function Child() {} Child.prototype = proto; return new Child(); }; /** * Create a promise whose fate is determined by resolver * @constructor * @returns {Promise} promise * @name Promise */ function Promise(resolver, handler) { this._handler = resolver === Handler ? handler : init(resolver); } /** * Run the supplied resolver * @param resolver * @returns {makePromise.DeferredHandler} */ function init(resolver) { var handler = new DeferredHandler(); try { resolver(promiseResolve, promiseReject, promiseNotify); } catch (e) { promiseReject(e); } return handler; /** * Transition from pre-resolution state to post-resolution state, notifying * all listeners of the ultimate fulfillment or rejection * @param {*} x resolution value */ function promiseResolve (x) { handler.resolve(x); } /** * Reject this promise with reason, which will be used verbatim * @param {Error|*} reason rejection reason, strongly suggested * to be an Error type */ function promiseReject (reason) { handler.reject(reason); } /** * Issue a progress event, notifying all progress listeners * @param {*} x progress event payload to pass to all listeners */ function promiseNotify (x) { handler.notify(x); } } // Creation Promise.resolve = resolve; Promise.reject = reject; Promise.never = never; Promise._defer = defer; /** * Returns a trusted promise. If x is already a trusted promise, it is * returned, otherwise returns a new trusted Promise which follows x. * @param {*} x * @return {Promise} promise */ function resolve(x) { return isPromise(x) ? x : new Promise(Handler, new AsyncHandler(getHandler(x))); } /** * Return a reject promise with x as its reason (x is used verbatim) * @param {*} x * @returns {Promise} rejected promise */ function reject(x) { return new Promise(Handler, new AsyncHandler(new RejectedHandler(x))); } /** * Return a promise that remains pending forever * @returns {Promise} forever-pending promise. */ function never() { return foreverPendingPromise; // Should be frozen } /** * Creates an internal {promise, resolver} pair * @private * @returns {Promise} */ function defer() { return new Promise(Handler, new DeferredHandler()); } // Transformation and flow control /** * Transform this promise's fulfillment value, returning a new Promise * for the transformed result. If the promise cannot be fulfilled, onRejected * is called with the reason. onProgress *may* be called with updates toward * this promise's fulfillment. * @param {function=} onFulfilled fulfillment handler * @param {function=} onRejected rejection handler * @deprecated @param {function=} onProgress progress handler * @return {Promise} new promise */ Promise.prototype.then = function(onFulfilled, onRejected) { var parent = this._handler; if (typeof onFulfilled !== 'function' && parent.join().state() > 0) { // Short circuit: value will not change, simply share handler return new Promise(Handler, parent); } var p = this._beget(); var child = p._handler; parent.when({ resolve: child.resolve, notify: child.notify, context: child, receiver: parent.receiver, fulfilled: onFulfilled, rejected: onRejected, progress: arguments.length > 2 ? arguments[2] : void 0 }); return p; }; /** * If this promise cannot be fulfilled due to an error, call onRejected to * handle the error. Shortcut for .then(undefined, onRejected) * @param {function?} onRejected * @return {Promise} */ Promise.prototype['catch'] = function(onRejected) { return this.then(void 0, onRejected); }; /** * Private function to bind a thisArg for this promise's handlers * @private * @param {object} thisArg `this` value for all handlers attached to * the returned promise. * @returns {Promise} */ Promise.prototype._bindContext = function(thisArg) { return new Promise(Handler, new BoundHandler(this._handler, thisArg)); }; /** * Creates a new, pending promise of the same type as this promise * @private * @returns {Promise} */ Promise.prototype._beget = function() { var parent = this._handler; var child = new DeferredHandler(parent.receiver, parent.join().context); return new this.constructor(Handler, child); }; /** * Check if x is a rejected promise, and if so, delegate to handler._fatal * @private * @param {*} x */ Promise.prototype._maybeFatal = function(x) { if(!maybeThenable(x)) { return; } var handler = getHandler(x); var context = this._handler.context; handler.catchError(function() { this._fatal(context); }, handler); }; // Array combinators Promise.all = all; Promise.race = race; /** * Return a promise that will fulfill when all promises in the * input array have fulfilled, or will reject when one of the * promises rejects. * @param {array} promises array of promises * @returns {Promise} promise for array of fulfillment values */ function all(promises) { /*jshint maxcomplexity:8*/ var resolver = new DeferredHandler(); var pending = promises.length >>> 0; var results = new Array(pending); var i, h, x, s; for (i = 0; i < promises.length; ++i) { x = promises[i]; if (x === void 0 && !(i in promises)) { --pending; continue; } if (maybeThenable(x)) { h = isPromise(x) ? x._handler.join() : getHandlerUntrusted(x); s = h.state(); if (s === 0) { resolveOne(resolver, results, h, i); } else if (s > 0) { results[i] = h.value; --pending; } else { resolver.become(h); break; } } else { results[i] = x; --pending; } } if(pending === 0) { resolver.become(new FulfilledHandler(results)); } return new Promise(Handler, resolver); function resolveOne(resolver, results, handler, i) { handler.map(function(x) { results[i] = x; if(--pending === 0) { this.become(new FulfilledHandler(results)); } }, resolver); } } /** * Fulfill-reject competitive race. Return a promise that will settle * to the same state as the earliest input promise to settle. * * WARNING: The ES6 Promise spec requires that race()ing an empty array * must return a promise that is pending forever. This implementation * returns a singleton forever-pending promise, the same singleton that is * returned by Promise.never(), thus can be checked with === * * @param {array} promises array of promises to race * @returns {Promise} if input is non-empty, a promise that will settle * to the same outcome as the earliest input promise to settle. if empty * is empty, returns a promise that will never settle. */ function race(promises) { // Sigh, race([]) is untestable unless we return *something* // that is recognizable without calling .then() on it. if(Object(promises) === promises && promises.length === 0) { return never(); } var h = new DeferredHandler(); var i, x; for(i=0; i<promises.length; ++i) { x = promises[i]; if (x !== void 0 && i in promises) { getHandler(x).chain(h, h.resolve, h.reject); } } return new Promise(Handler, h); } // Promise internals /** * Get an appropriate handler for x, without checking for cycles * @private * @param {*} x * @returns {object} handler */ function getHandler(x) { if(isPromise(x)) { return x._handler.join(); } return maybeThenable(x) ? getHandlerUntrusted(x) : new FulfilledHandler(x); } function isPromise(x) { return x instanceof Promise; } /** * Get a handler for potentially untrusted thenable x * @param {*} x * @returns {object} handler */ function getHandlerUntrusted(x) { try { var untrustedThen = x.then; return typeof untrustedThen === 'function' ? new ThenableHandler(untrustedThen, x) : new FulfilledHandler(x); } catch(e) { return new RejectedHandler(e); } } /** * Handler for a promise that is pending forever * @private * @constructor */ function Handler() {} Handler.prototype.when = Handler.prototype.resolve = Handler.prototype.reject = Handler.prototype.notify = Handler.prototype._fatal = Handler.prototype._unreport = Handler.prototype._report = noop; Handler.prototype.inspect = toPendingState; Handler.prototype._state = 0; Handler.prototype.state = function() { return this._state; }; /** * Recursively collapse handler chain to find the handler * nearest to the fully resolved value. * @returns {object} handler nearest the fully resolved value */ Handler.prototype.join = function() { var h = this; while(h.handler !== void 0) { h = h.handler; } return h; }; Handler.prototype.chain = function(to, fulfilled, rejected, progress) { this.when({ resolve: noop, notify: noop, context: void 0, receiver: to, fulfilled: fulfilled, rejected: rejected, progress: progress }); }; Handler.prototype.map = function(f, to) { this.chain(to, f, to.reject, to.notify); }; Handler.prototype.catchError = function(f, to) { this.chain(to, to.resolve, f, to.notify); }; Handler.prototype.fold = function(to, f, z) { this.join().map(function(x) { getHandler(z).map(function(z) { this.resolve(tryCatchReject2(f, z, x, this.receiver)); }, this); }, to); }; /** * Handler that manages a queue of consumers waiting on a pending promise * @private * @constructor */ function DeferredHandler(receiver, inheritedContext) { Promise.createContext(this, inheritedContext); this.consumers = void 0; this.receiver = receiver; this.handler = void 0; this.resolved = false; } inherit(Handler, DeferredHandler); DeferredHandler.prototype._state = 0; DeferredHandler.prototype.inspect = function() { return this.resolved ? this.join().inspect() : toPendingState(); }; DeferredHandler.prototype.resolve = function(x) { if(!this.resolved) { this.become(getHandler(x)); } }; DeferredHandler.prototype.reject = function(x) { if(!this.resolved) { this.become(new RejectedHandler(x)); } }; DeferredHandler.prototype.join = function() { if (this.resolved) { var h = this; while(h.handler !== void 0) { h = h.handler; if(h === this) { return this.handler = new Cycle(); } } return h; } else { return this; } }; DeferredHandler.prototype.run = function() { var q = this.consumers; var handler = this.join(); this.consumers = void 0; for (var i = 0; i < q.length; ++i) { handler.when(q[i]); } }; DeferredHandler.prototype.become = function(handler) { this.resolved = true; this.handler = handler; if(this.consumers !== void 0) { tasks.enqueue(this); } if(this.context !== void 0) { handler._report(this.context); } }; DeferredHandler.prototype.when = function(continuation) { if(this.resolved) { tasks.enqueue(new ContinuationTask(continuation, this.handler)); } else { if(this.consumers === void 0) { this.consumers = [continuation]; } else { this.consumers.push(continuation); } } }; DeferredHandler.prototype.notify = function(x) { if(!this.resolved) { tasks.enqueue(new ProgressTask(this, x)); } }; DeferredHandler.prototype._report = function(context) { this.resolved && this.handler.join()._report(context); }; DeferredHandler.prototype._unreport = function() { this.resolved && this.handler.join()._unreport(); }; DeferredHandler.prototype._fatal = function(context) { var c = typeof context === 'undefined' ? this.context : context; this.resolved && this.handler.join()._fatal(c); }; /** * Abstract base for handler that delegates to another handler * @private * @param {object} handler * @constructor */ function DelegateHandler(handler) { this.handler = handler; } inherit(Handler, DelegateHandler); DelegateHandler.prototype.inspect = function() { return this.join().inspect(); }; DelegateHandler.prototype._report = function(context) { this.join()._report(context); }; DelegateHandler.prototype._unreport = function() { this.join()._unreport(); }; /** * Wrap another handler and force it into a future stack * @private * @param {object} handler * @constructor */ function AsyncHandler(handler) { DelegateHandler.call(this, handler); } inherit(DelegateHandler, AsyncHandler); AsyncHandler.prototype.when = function(continuation) { tasks.enqueue(new ContinuationTask(continuation, this.join())); }; /** * Handler that follows another handler, injecting a receiver * @private * @param {object} handler another handler to follow * @param {object=undefined} receiver * @constructor */ function BoundHandler(handler, receiver) { DelegateHandler.call(this, handler); this.receiver = receiver; } inherit(DelegateHandler, BoundHandler); BoundHandler.prototype.when = function(continuation) { // Because handlers are allowed to be shared among promises, // each of which possibly having a different receiver, we have // to insert our own receiver into the chain if it has been set // so that callbacks (f, r, u) will be called using our receiver if(this.receiver !== void 0) { continuation.receiver = this.receiver; } this.join().when(continuation); }; /** * Handler that wraps an untrusted thenable and assimilates it in a future stack * @private * @param {function} then * @param {{then: function}} thenable * @constructor */ function ThenableHandler(then, thenable) { DeferredHandler.call(this); tasks.enqueue(new AssimilateTask(then, thenable, this)); } inherit(DeferredHandler, ThenableHandler); /** * Handler for a fulfilled promise * @private * @param {*} x fulfillment value * @constructor */ function FulfilledHandler(x) { Promise.createContext(this); this.value = x; } inherit(Handler, FulfilledHandler); FulfilledHandler.prototype._state = 1; FulfilledHandler.prototype.inspect = function() { return { state: 'fulfilled', value: this.value }; }; FulfilledHandler.prototype.when = function(cont) { var x; if (typeof cont.fulfilled === 'function') { Promise.enterContext(this); x = tryCatchReject(cont.fulfilled, this.value, cont.receiver); Promise.exitContext(); } else { x = this.value; } cont.resolve.call(cont.context, x); }; var id = 0; /** * Handler for a rejected promise * @private * @param {*} x rejection reason * @constructor */ function RejectedHandler(x) { Promise.createContext(this); this.id = ++id; this.value = x; this.handled = false; this.reported = false; this._report(); } inherit(Handler, RejectedHandler); RejectedHandler.prototype._state = -1; RejectedHandler.prototype.inspect = function() { return { state: 'rejected', reason: this.value }; }; RejectedHandler.prototype.when = function(cont) { var x; if (typeof cont.rejected === 'function') { this._unreport(); Promise.enterContext(this); x = tryCatchReject(cont.rejected, this.value, cont.receiver); Promise.exitContext(); } else { x = new Promise(Handler, this); } cont.resolve.call(cont.context, x); }; RejectedHandler.prototype._report = function(context) { tasks.afterQueue(reportUnhandled, this, context); }; RejectedHandler.prototype._unreport = function() { this.handled = true; tasks.afterQueue(reportHandled, this); }; RejectedHandler.prototype._fatal = function(context) { Promise.onFatalRejection(this, context); }; function reportUnhandled(rejection, context) { if(!rejection.handled) { rejection.reported = true; Promise.onPotentiallyUnhandledRejection(rejection, context); } } function reportHandled(rejection) { if(rejection.reported) { Promise.onPotentiallyUnhandledRejectionHandled(rejection); } } // Unhandled rejection hooks // By default, everything is a noop // TODO: Better names: "annotate"? Promise.createContext = Promise.enterContext = Promise.exitContext = Promise.onPotentiallyUnhandledRejection = Promise.onPotentiallyUnhandledRejectionHandled = Promise.onFatalRejection = noop; // Errors and singletons var foreverPendingHandler = new Handler(); var foreverPendingPromise = new Promise(Handler, foreverPendingHandler); function Cycle() { RejectedHandler.call(this, new TypeError('Promise cycle')); } inherit(RejectedHandler, Cycle); // Snapshot states /** * Creates a pending state snapshot * @private * @returns {{state:'pending'}} */ function toPendingState() { return { state: 'pending' }; } // Task runners /** * Run a single consumer * @private * @constructor */ function ContinuationTask(continuation, handler) { this.continuation = continuation; this.handler = handler; } ContinuationTask.prototype.run = function() { this.handler.join().when(this.continuation); }; /** * Run a queue of progress handlers * @private * @constructor */ function ProgressTask(handler, value) { this.handler = handler; this.value = value; } ProgressTask.prototype.run = function() { var q = this.handler.consumers; if(q === void 0) { return; } // First progress handler is at index 1 for (var i = 0; i < q.length; ++i) { this._notify(q[i]); } }; ProgressTask.prototype._notify = function(continuation) { var x = typeof continuation.progress === 'function' ? tryCatchReturn(continuation.progress, this.value, continuation.receiver) : this.value; continuation.notify.call(continuation.context, x); }; /** * Assimilate a thenable, sending it's value to resolver * @private * @param {function} then * @param {object|function} thenable * @param {object} resolver * @constructor */ function AssimilateTask(then, thenable, resolver) { this._then = then; this.thenable = thenable; this.resolver = resolver; } AssimilateTask.prototype.run = function() { var h = this.resolver; tryAssimilate(this._then, this.thenable, _resolve, _reject, _notify); function _resolve(x) { h.resolve(x); } function _reject(x) { h.reject(x); } function _notify(x) { h.notify(x); } }; function tryAssimilate(then, thenable, resolve, reject, notify) { try { then.call(thenable, resolve, reject, notify); } catch (e) { reject(e); } } // Other helpers /** * @param {*} x * @returns {boolean} false iff x is guaranteed not to be a thenable */ function maybeThenable(x) { return (typeof x === 'object' || typeof x === 'function') && x !== null; } /** * Return f.call(thisArg, x), or if it throws return a rejected promise for * the thrown exception * @private */ function tryCatchReject(f, x, thisArg) { try { return f.call(thisArg, x); } catch(e) { return reject(e); } } /** * Same as above, but includes the extra argument parameter. * @private */ function tryCatchReject2(f, x, y, thisArg) { try { return f.call(thisArg, x, y); } catch(e) { return reject(e); } } /** * Return f.call(thisArg, x), or if it throws, *return* the exception * @private */ function tryCatchReturn(f, x, thisArg) { try { return f.call(thisArg, x); } catch(e) { return e; } } function inherit(Parent, Child) { Child.prototype = objectCreate(Parent.prototype); Child.prototype.constructor = Child; } function noop() {} return Promise; }; }); }(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(); })); },{}],7:[function(require,module,exports){ /** @license MIT License (c) copyright 2010-2014 original author or authors */ /** @author Brian Cavalier */ /** @author John Hann */ (function(define) { 'use strict'; define(function(require) { var Queue = require('./Queue'); // Credit to Twisol (https://github.com/Twisol) for suggesting // this type of extensible queue + trampoline approach for next-tick conflation. function Scheduler(enqueue) { this._enqueue = enqueue; this._handlerQueue = new Queue(15); this._afterQueue = new Queue(5); this._running = false; var self = this; this.drain = function() { self._drain(); }; } /** * Enqueue a task. If the queue is not currently scheduled to be * drained, schedule it. * @param {function} task */ Scheduler.prototype.enqueue = function(task) { this._handlerQueue.push(task); if(!this._running) { this._running = true; this._enqueue(this.drain); } }; Scheduler.prototype.afterQueue = function(f, x, y) { this._afterQueue.push(f); this._afterQueue.push(x); this._afterQueue.push(y); if(!this._running) { this._running = true; this._enqueue(this.drain); } }; /** * Drain the handler queue entirely, being careful to allow the * queue to be extended while it is being processed, and to continue * processing until it is truly empty. */ Scheduler.prototype._drain = function() { var q = this._handlerQueue; while(q.length > 0) { q.shift().run(); } this._running = false; q = this._afterQueue; while(q.length > 0) { q.shift()(q.shift(), q.shift()); } }; return Scheduler; }); }(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(require); })); },{"./Queue":3}],8:[function(require,module,exports){ /** @license MIT License (c) copyright 2010-2014 original author or authors */ /** @author Brian Cavalier */ /** @author John Hann */ (function(define) { 'use strict'; define(function(require) { /*global setTimeout,clearTimeout*/ var cjsRequire, vertx, setTimer, clearTimer; cjsRequire = require; try { vertx = cjsRequire('vertx'); setTimer = function (f, ms) { return vertx.setTimer(ms, f); }; clearTimer = vertx.cancelTimer; } catch (e) { setTimer = function(f, ms) { return setTimeout(f, ms); }; clearTimer = function(t) { return clearTimeout(t); }; } return { set: setTimer, clear: clearTimer }; }); }(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(require); })); },{}]},{},[1]) (1) }); ;