Created
July 17, 2014 20:44
-
-
Save brianleroux/713d9bd39a9bda4db106 to your computer and use it in GitHub Desktop.
demonstrates refactoring a bunch of node style callbacks with async
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* setup a pile of nodejs style methods that accept nodejs style callbacks (where err is the first argument and data the second)*/ | |
var obj = {msg:'before'} | |
function first(obj, cb) { | |
console.log('first', obj.msg) | |
obj.msg += ' ... first' | |
cb(null, obj) | |
} | |
function second(obj, cb) { | |
console.log('second', obj.msg) | |
obj.msg += ' ... second' | |
cb(null, obj) | |
} | |
function third(obj, cb) { | |
console.log('third', obj.msg) | |
obj.msg += ' ... third' | |
cb(null, obj) | |
} | |
/** this is probably ok but smells terrible and encouraging a likely bad maintenance path | |
* (just one more cb is no big deal..., next thing you know your 20 deep | |
* | |
* | |
*/ | |
first(obj, function(err, d) { | |
second(d, function(err, data2) { | |
third(data2, function(err, data3) { | |
console.log('final callback', data3) | |
}) | |
}) | |
}) | |
console.log('\n') | |
/** | |
* lets clean this up w/ async, making it easier to add flat functions than nested ones | |
*/ | |
var async = require('async') | |
var obj = {msg:'before'} | |
async.series([ | |
function(next) { | |
first(obj, next) | |
}, | |
function(next) { | |
second(obj, next) | |
}, | |
function(next) { | |
third(obj, next) | |
}], | |
function(results) { | |
console.log('final callback again', obj)}) | |
console.log('\n') | |
/** | |
* we can do even better still, removing that boilerplate continuation passing style with async.apply | |
*/ | |
var obj = {msg:'before'} | |
// lets test the failure condition aborting on the second callback | |
function fail(obj, cb) { | |
cb(new Error('omg')) | |
} | |
async.series([ | |
async.apply(first, obj), | |
async.apply(fail, obj), | |
async.apply(third, obj) | |
], | |
function(err) { | |
console.log('final callback again', err, obj) | |
}) | |
/** | |
* but this is still very hadcoded and has a lot of boilerplate machinery | |
* lets distill the functionality of calling a series of methods, with an object as the first argument and a callback as the second, finally aborting if an error is passed | |
*/ | |
function series(methods, obj, cb) { | |
var m = methods.map(function(method) { | |
return async.apply(method, obj) | |
}) | |
async.series(m, function(err) { cb(err, obj)}) | |
} | |
// the final iteration | |
// | |
// - flat and easy to reason about | |
// - easy to add and remove steps | |
// - traps errors | |
// | |
series([first, second, third], obj, function(err, d) { | |
console.log('final final final', err, d) | |
}) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment