Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Naïve parallel/chain implementation for asynchronous functions taking node-style callbacks
var concat = [].concat, slice = [].slice;
function chain(fns, initialArgs, callback) {
(function next(error) { // `next` is the callback for each chained function
if (error) { callback(error); return; }
var fn = fns.shift();
if (fn) {
fn.apply(null, slice.call(arguments, 1).concat(next));
} else {
callback.apply(null, arguments);
}
}.apply(null, [null].concat(initialArgs)));
}
function parallel(functions, callback) {
function invokeCallback(error) {
if (!callback) return;
var result = concat.apply([error], results);
callback.apply(null, result);
callback = null; // prevent double execution
}
function pingback(callbackIndex, receivedArgs) {
if (executedCallbacks[callbackIndex]) { return; }
var error = receivedArgs[0];
results[callbackIndex] = slice.call(receivedArgs, 1); // save non-error values
executedCallbacks[callbackIndex] = true; // add to executed callbacks
// execute early in case of error, otherwise wait for all callbacks to execute
if (error || executedCallbacks.indexOf(undefined) === -1) {
invokeCallback(error || null);
}
}
var numFunctions = functions.length;
var results = Array(numFunctions);
var executedCallbacks = Array.apply(null, Array(numFunctions));
for (var i = 0, length = functions.length; i < length; i += 1) {
functions[i](function(i) {
return function() { pingback(i, arguments); }
}(i));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.