public
Created

Waiters (promises/deferreds/futures)

  • Download Gist
waiter.js
JavaScript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
function Waiter(context) {
if (context) { this.context = context; }
}
 
Waiter.prototype.failed = function (cb) {
if (this.result) {
if (!this.success) { cb.apply(this.context || this, this.result); }
} else {
if (!this.failedCbs) { this.failedCbs = []; }
this.failedCbs.push(cb);
}
return this;
};
 
Waiter.prototype.then = function (cb) {
if (this.result) {
if (this.success) { cb.apply(this.context || this, this.result); }
} else {
if (!this.thenCbs) { this.thenCbs = []; }
this.thenCbs.push(cb);
}
return this;
};
 
Waiter.prototype.fail = function () {
if (this.result) { return; }
 
this.result = arguments;
this.success = false;
 
var cbs = this.failedCbs;
 
delete this.failedCbs;
delete this.thenCbs;
 
if (!cbs) { return; }
 
var i, len = cbs.length;
for (i = 0; i < len; i++) {
cbs[i].apply(this.context || this, arguments);
}
};
 
Waiter.prototype.failAfter = function (ms) {
var waiter = this;
setTimeout(function () {
waiter.fail();
}, ms);
};
 
Waiter.prototype.finish = function () {
if (this.result) { return; }
 
this.result = arguments;
this.success = true;
 
var cbs = this.thenCbs;
 
delete this.failedCbs;
delete this.thenCbs;
 
if (!cbs) { return; }
 
var i, len = cbs.length;
for (i = 0; i < len; i++) {
cbs[i].apply(this.context || this, arguments);
}
};
 
Waiter.join = function (list) {
var waiters = [].slice.call(list instanceof Array ? list : arguments);
 
var count = waiters.length;
 
var w = new Waiter();
w.waiters = waiters;
if (!count) {
w.finish();
return w;
}
 
w.remaining = count;
 
var then = Waiter.joinThen.bind(w), failed = Waiter.joinFailed.bind(w);
 
var i;
for (i = 0; i < count; i++) {
waiters[i].then(then).failed(failed);
}
return w;
};
 
Waiter.joinThen = function () {
if (!this.remaining || --this.remaining) { return; }
delete this.remaining;
 
var result = [], i, len = this.waiters.length;
for (i = 0; i < len; i++) {
result.push.apply(result, this.waiters[i].result);
}
 
this.finish.apply(this, result);
};
 
Waiter.joinFailed = function () {
if (!this.remaining) { return; }
delete this.remaining;
 
this.fail.apply(this, arguments);
};

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.