|
|
@ -0,0 +1,124 @@ |
|
|
|
/** |
|
|
|
* A queue |
|
|
|
* @param {Object} options |
|
|
|
* Available options: |
|
|
|
* - delay: number When a number, the queue will be flushed |
|
|
|
* automatically after an inactivity of this delay |
|
|
|
* in milliseconds. |
|
|
|
* When false (default), the queue is not flushed |
|
|
|
* - max: number When the queue exceeds the given maximum number |
|
|
|
* of entries, the queue is flushed automatically. |
|
|
|
* Default value of max is Infinity. |
|
|
|
* @constructor |
|
|
|
*/ |
|
|
|
function Queue(options) { |
|
|
|
// options
|
|
|
|
this.delay = options && typeof options.delay === 'number' ? options.delay : false; |
|
|
|
this.max = options && typeof options.max === 'number' ? options.max : Infinity; |
|
|
|
|
|
|
|
// properties
|
|
|
|
this._queue = []; |
|
|
|
this._timeout = null; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Extend an object with queuing functionality. |
|
|
|
* The object will be extended with a function flush, and the methods provided |
|
|
|
* in options.replace will be replaced with queued ones. |
|
|
|
* @param {Object} object |
|
|
|
* @param {Object} options |
|
|
|
* Available options: |
|
|
|
* - replace: Array.<string> |
|
|
|
* A list with method names of the methods |
|
|
|
* on the object to be replaced with queued ones. |
|
|
|
* - delay: number When a number, the queue will be flushed |
|
|
|
* automatically after an inactivity of this delay |
|
|
|
* in milliseconds. |
|
|
|
* When false (default), the queue is not flushed |
|
|
|
* - max: number When the queue exceeds the given maximum number |
|
|
|
* of entries, the queue is flushed automatically. |
|
|
|
* Default value of max is Infinity. |
|
|
|
*/ |
|
|
|
Queue.extend = function (object, options) { |
|
|
|
var queue = new Queue(options); |
|
|
|
|
|
|
|
if (object.flush !== undefined) { |
|
|
|
throw new Error('Target object already has a property flush'); |
|
|
|
} |
|
|
|
object.flush = function () { |
|
|
|
queue.flush(); |
|
|
|
}; |
|
|
|
|
|
|
|
if (options && options.replace) { |
|
|
|
for (var i = 0; i < options.replace.length; i++) { |
|
|
|
queue.replace(object, options.replace[i]); |
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
/** |
|
|
|
* Replace a method on an object with a queued version |
|
|
|
* @param {Object} object Object having the method |
|
|
|
* @param {string} method The method name |
|
|
|
*/ |
|
|
|
Queue.prototype.replace = function(object, method) { |
|
|
|
var me = this; |
|
|
|
var original = object[method]; |
|
|
|
if (!original) { |
|
|
|
throw new Error('Method ' + method + ' undefined'); |
|
|
|
} |
|
|
|
|
|
|
|
object[method] = function () { |
|
|
|
// create an Array with the arguments
|
|
|
|
var args = []; |
|
|
|
for (var i = 0; i < arguments.length; i++) { |
|
|
|
args[i] = arguments[i]; |
|
|
|
} |
|
|
|
|
|
|
|
// add this call to the queue
|
|
|
|
me.queue({ |
|
|
|
args: args, |
|
|
|
fn: original, |
|
|
|
context: this |
|
|
|
}); |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
/** |
|
|
|
* Queue a call |
|
|
|
* @param {function | {fn: function, args: Array} | {fn: function, args: Array, context: Object}} entry |
|
|
|
*/ |
|
|
|
Queue.prototype.queue = function(entry) { |
|
|
|
if (typeof entry === 'function') { |
|
|
|
this._queue.push({fn: entry}); |
|
|
|
} |
|
|
|
else { |
|
|
|
this._queue.push(entry); |
|
|
|
} |
|
|
|
|
|
|
|
// flush when the maximum is exceeded.
|
|
|
|
if (this._queue.length > this.max) { |
|
|
|
this.flush(); |
|
|
|
} |
|
|
|
|
|
|
|
// flush after a period of inactivity when a delay is configured
|
|
|
|
if (typeof this.delay === 'number') { |
|
|
|
var me = this; |
|
|
|
clearTimeout(this._timeout); |
|
|
|
this._timeout = setTimeout(function () { |
|
|
|
me.flush(); |
|
|
|
}, this.delay); |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
/** |
|
|
|
* Flush all queued calls |
|
|
|
*/ |
|
|
|
Queue.prototype.flush = function () { |
|
|
|
while (this._queue.length > 0) { |
|
|
|
var entry = this._queue.shift(); |
|
|
|
entry.fn.apply(entry.context || entry.fn, entry.args || []); |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
module.exports = Queue; |