%PDF- %PDF-
Direktori : /home/opti/workflow/node_modules/directmail/lib/ |
Current File : /home/opti/workflow/node_modules/directmail/lib/queue.js |
'use strict'; // expose to the world module.exports = function() { return new Queue(); }; /** * Creates a queue object * * @constructor */ function Queue() { this._instantQueue = []; this._sortedQueue = []; this._shiftTimer = null; this._callbackQueue = []; } /** * Sets a callback to be run when something comes available from the queue * * @param {Function} callback Callback function to run with queue element as an argument */ Queue.prototype.get = function(callback) { if (this._instantQueue.length) { callback(this._instantQueue.pop()); } else { this._callbackQueue.unshift(callback); } }; /** * Adds an element to the queue. If delay (ms) is set, the data will not be available before * specified delay has passed. Otherwise the data will be available for processing immediatelly. * * @param {Mixed} data Value to be queued * @param {Number} [delay] If set, delay the availability of the data by {delay} milliseconds */ Queue.prototype.insert = function(data, delay) { var container, added = -1; if (typeof delay != 'number') { this._instantQueue.unshift(data); this._processInsert(); return true; } else { container = { data: data, available: Date.now() + delay }; for (var i = 0, len = this._sortedQueue.length; i < len; i++) { if (this._sortedQueue[i].available >= container.available) { this._sortedQueue.splice(i, 0, container); added = i; break; } } if (added < 0) { this._sortedQueue.push(container); added = 0; } if (added === 0) { this._updateShiftTimer(); } } }; /** * Clears previous timer and creates a new one (if needed) to process the element * in the queue that needs to be processed first. */ Queue.prototype._updateShiftTimer = function() { var nextShift, now = Date.now(); clearTimeout(this._shiftTimer); if (!this._sortedQueue.length) { return; } nextShift = this._sortedQueue[0].available; if (nextShift <= now) { this._shiftSorted(); } else { setTimeout(this._shiftSorted.bind(this), // add +15ms to ensure that data is already available when the timer is fired this._sortedQueue[0].available - Date.now() + 15); } }; /** * Moves an element from the delayed queue to the immediate queue if an elmenet * becomes avilable */ Queue.prototype._shiftSorted = function() { var container; if (!this._sortedQueue.length) { return; } if (this._sortedQueue[0].available <= Date.now()) { container = this._sortedQueue.shift(); this.insert(container.data); } this._updateShiftTimer(); }; /** * If data from a queue is available and a callback is set, run the callback * with available data */ Queue.prototype._processInsert = function() { if (this._instantQueue.length && this._callbackQueue.length) { this._callbackQueue.pop()(this._instantQueue.pop()); } };