|
module.exports = Pend; |
|
|
|
function Pend() { |
|
this.pending = 0; |
|
this.max = Infinity; |
|
this.listeners = []; |
|
this.waiting = []; |
|
this.error = null; |
|
} |
|
|
|
Pend.prototype.go = function(fn) { |
|
if (this.pending < this.max) { |
|
pendGo(this, fn); |
|
} else { |
|
this.waiting.push(fn); |
|
} |
|
}; |
|
|
|
Pend.prototype.wait = function(cb) { |
|
if (this.pending === 0) { |
|
cb(this.error); |
|
} else { |
|
this.listeners.push(cb); |
|
} |
|
}; |
|
|
|
Pend.prototype.hold = function() { |
|
return pendHold(this); |
|
}; |
|
|
|
function pendHold(self) { |
|
self.pending += 1; |
|
var called = false; |
|
return onCb; |
|
function onCb(err) { |
|
if (called) throw new Error("callback called twice"); |
|
called = true; |
|
self.error = self.error || err; |
|
self.pending -= 1; |
|
if (self.waiting.length > 0 && self.pending < self.max) { |
|
pendGo(self, self.waiting.shift()); |
|
} else if (self.pending === 0) { |
|
var listeners = self.listeners; |
|
self.listeners = []; |
|
listeners.forEach(cbListener); |
|
} |
|
} |
|
function cbListener(listener) { |
|
listener(self.error); |
|
} |
|
} |
|
|
|
function pendGo(self, fn) { |
|
fn(pendHold(self)); |
|
} |
|
|