56 lines
		
	
	
		
			1.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			56 lines
		
	
	
		
			1.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| 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));
 | |
| }
 |