Skip to content

Instantly share code, notes, and snippets.

@ptdecker
Last active December 6, 2016 15:05
Show Gist options
  • Select an option

  • Save ptdecker/733548b08d12161c2ed0 to your computer and use it in GitHub Desktop.

Select an option

Save ptdecker/733548b08d12161c2ed0 to your computer and use it in GitHub Desktop.
Node.js Serial Execution of an Array of Callback Functions
/* Control Flow 4 - Serial Execution of an Array of Callback Functions
*
* Based on:
* - http://book.mixu.net/node/ch7.html
* - https://github.com/mixu
*
* Revised based upon comments from 'lanzz' to use 'process.nextTick(next)' instead of 'next()'
* Revised based upon comments from 'Israel' to use "typeof(callback) != 'undefined'"
*
* The 'Array.prototype.slice.call(arguments)' usage is a JavaScript trick and explained here:
* - http://mariapacana.tumblr.com/post/79170518832/javascript-tricks
* - http://stackoverflow.com/questions/7056925/how-does-array-prototype-slice-call-work
*
* Characteristics:
* - Flow control construct 'series' is recursive
* - Runs a number of operations sequentially
* - Only starts one async operation at a time (no concurrency)
* - Ensures that the async function complete in order
*
* Variations:
* - The way in which the result is collected (manual or via a “stashing” callback)
* - How error handling is done (manually in each sub-function, or via a dedicated, additional function)
* - Since execution is sequential, there is no need for a “final” callback
*
* Tags: sequential, no-concurrency, no-concurrency-control, array of functions work queue
*/
/*
* A Simulated Asynchronous Function
*/
function async(arg, callback) {
var delay = Math.floor(1000 * Math.random());
console.log('Do something with "' + arg + '", and return ' + delay + 'ms later');
setTimeout(function() {
result = arg; // Keep results same as argument so impact of async can be viewed
callback(result);
}, delay);
}
/*
* Simulated Completion Function
*/
function final(results) {
console.log('Done', results);
console.log(process.hrtime(start)[0] + "." + (process.hrtime(start)[1] / 1000000).toFixed(0) + " sec(s) total time");
}
/*
* Recursive 'Series' Flow Control Construct with Callback Functions Passed as a Work Queue
*/
function series(results, callbacks, last) {
function next() {
var callback = callbacks.shift();
if (typeof(callback) != 'undefined') {
callback(function() {
results.push(Array.prototype.slice.call(arguments));
console.log("Results so far: ", results);
next();
});
} else {
last(results);
}
}
process.nextTick(next);
}
/*
* Main
*/
var start = process.hrtime();
var results = [];
series(results, [
function(next) {
async(1, next);
},
function(next) {
async(2, next);
},
function(next) {
async(3, next);
},
function(next) {
async(4, next);
},
function(next) {
async(5, next);
},
function(next) {
async(6, next);
},
function(next) {
async(7, next);
},
function(next) {
async(8, next);
},
], final);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment