| ; | |
| function Queue(options) { | |
| if (!(this instanceof Queue)) { | |
| return new Queue(options); | |
| } | |
| options = options || {}; | |
| this.concurrency = options.concurrency || Infinity; | |
| this.pending = 0; | |
| this.jobs = []; | |
| this.cbs = []; | |
| this._done = done.bind(this); | |
| } | |
| var arrayAddMethods = [ | |
| 'push', | |
| 'unshift', | |
| 'splice' | |
| ]; | |
| arrayAddMethods.forEach(function(method) { | |
| Queue.prototype[method] = function() { | |
| var methodResult = Array.prototype[method].apply(this.jobs, arguments); | |
| this._run(); | |
| return methodResult; | |
| }; | |
| }); | |
| Object.defineProperty(Queue.prototype, 'length', { | |
| get: function() { | |
| return this.pending + this.jobs.length; | |
| } | |
| }); | |
| Queue.prototype._run = function() { | |
| if (this.pending === this.concurrency) { | |
| return; | |
| } | |
| if (this.jobs.length) { | |
| var job = this.jobs.shift(); | |
| this.pending++; | |
| job(this._done); | |
| this._run(); | |
| } | |
| if (this.pending === 0) { | |
| while (this.cbs.length !== 0) { | |
| var cb = this.cbs.pop(); | |
| process.nextTick(cb); | |
| } | |
| } | |
| }; | |
| Queue.prototype.onDone = function(cb) { | |
| if (typeof cb === 'function') { | |
| this.cbs.push(cb); | |
| this._run(); | |
| } | |
| }; | |
| function done() { | |
| this.pending--; | |
| this._run(); | |
| } | |
| module.exports = Queue; | |