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