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)); | |
} | |