JavaScript
module.exports = asyncbuilder;
function asyncbuilder(mainCallBack) {
if (!(this instanceof asyncbuilder)) return new asyncbuilder(mainCallBack);
var results = [];
var pending = 0;
var isComplete = false;
var spent = false;
var asyncErr = null;
this.append = append;
this.asyncAppend = asyncAppend;
this.complete = complete;
function append(result) {
if (spent) throw new Error('asyncbuilder append after mainCallBack');
if (isComplete) {
asyncErr = asyncErr || new Error('asyncbuilder append after complete.');
return;
}
results.push(result);
}
function asyncAppend() {
if (spent) throw new Error('asyncbuilder asyncAppend after mainCallBack');
if (isComplete) {
asyncErr = asyncErr || new Error('asyncbuilder asyncAppend after complete.');
return function(){};
}
var slot = results.push('') - 1;
pending++;
return function(err, result) {
pending--;
asyncErr = asyncErr || err;
results[slot] = result;
if (isComplete && !spent && !pending) {
spent = true;
mainCallBack(asyncErr, results);
}
};
}
function complete() {
isComplete = true;
if (!pending && !spent) {
spent = true;
process.nextTick(function() {
mainCallBack(asyncErr, results);
});
}
}
}