Permalink
Browse files

refactoring and unit test improvements

  • Loading branch information...
caolan committed May 27, 2010
1 parent 950183f commit cf648d7f4a10895eccb84f9e673cc8e6b576f369
Showing with 229 additions and 226 deletions.
  1. +128 −158 lib/async.js
  2. +101 −68 test/test-async.js
View
@@ -1,127 +1,6 @@
var events = require('events');
-exports.auto = function(tasks, callback){
- callback = callback || function(){};
- var keys = Object.keys(tasks);
- if(!keys.length) return callback(null);
-
- var completed = [];
- var emitter = new events.EventEmitter();
- emitter.addListener('taskComplete', function(){
- if(completed.length == keys.length){
- callback(null);
- }
- });
-
- keys.forEach(function(k){
- var task = (tasks[k] instanceof Function)? [tasks[k]]: tasks[k];
- var taskCallback = function(err){
- if(err){
- callback(err);
- // stop subsequent errors hitting the callback multiple times
- callback = function(){};
- }
- else {
- completed.push(k);
- emitter.emit('taskComplete');
- }
- };
- var requires = task.slice(0, Math.abs(task.length-1)) || [];
- var ready = function(){
- return requires.reduce(function(a,x){
- return (a && completed.indexOf(x) != -1);
- }, true);
- };
- if(ready()) task[task.length-1](taskCallback);
- else {
- var listener = function(){
- if(ready()){
- emitter.removeListener('taskComplete', listener);
- task[task.length-1](taskCallback);
- }
- };
- emitter.addListener('taskComplete', listener);
- }
- });
-};
-
-exports.waterfall = function(tasks, callback){
- callback = callback || function(){};
- var wrapIterator = function(iterator){
- return function(){
- var args = Array.prototype.slice.call(arguments);
- var next = iterator.next();
- if(next) args.push(wrapIterator(next));
- else args.push(callback);
- process.nextTick(function(){iterator.apply(null, args)});
- };
- };
- wrapIterator(exports.iterator(tasks))();
-};
-
-exports.parallel = function(tasks, callback){
- callback = callback || function(){};
- var results = [];
- tasks.forEach(function(fn){
- fn(function(err){
- if(err){
- callback(err);
- callback = function(){};
- }
- else {
- var args = Array.prototype.slice.call(arguments, 1);
- results.push((args.length > 1) ? args: args[0]);
- if(results.length == tasks.length){
- callback(null, results);
- }
- }
- });
- });
-};
-
-exports.series = function(tasks, callback){
- callback = callback || function(){};
- var results = [];
- var saveArgs = function(fn){
- return function(err){
- if(err){
- callback(err);
- callback = function(){};
- }
- else {
- var args = Array.prototype.slice.call(arguments, 1);
- results.push((args.length > 1) ? args: args[0]);
- fn.apply(null, args);
- }
- }
- };
- var wrapIterator = function(iterator){
- return saveArgs(function(){
- var next = iterator.next();
- if(next) iterator(wrapIterator(iterator.next()));
- else iterator(saveArgs(function(){
- callback(null, results.slice(1));
- }));
- });
- };
- wrapIterator(exports.iterator(tasks))();
-};
-
-exports.iterator = function(tasks){
- var makeCallback = function(index){
- var fn = function(){
- tasks[index].apply(null, arguments);
- return fn.next();
- }
- fn.next = function(){
- return (index < tasks.length-1)? makeCallback(index+1): undefined;
- }
- return fn;
- };
- return makeCallback(0);
-};
-
exports.forEach = function(arr, iterator, callback){
var completed = 0;
arr.forEach(function(x){
@@ -156,21 +35,24 @@ exports.forEachSeries = function(arr, iterator, callback){
iterate();
};
-exports.map = function(arr, iterator, callback){
- var results = [];
- exports.forEach(arr, function(x, callback){
- iterator(x, function(err, v){
- results.push(v);
- callback(err);
- });
- }, function(err){
- callback(err, results);
- });
+
+var doParallel = function(fn){
+ return function(){
+ var args = Array.prototype.slice.call(arguments);
+ return fn.apply(null, [exports.forEach].concat(args));
+ }
+};
+var doSeries = function(fn){
+ return function(){
+ var args = Array.prototype.slice.call(arguments);
+ return fn.apply(null, [exports.forEachSeries].concat(args));
+ }
};
-exports.mapSeries = function(arr, iterator, callback){
+
+var _map = function(eachfn, arr, iterator, callback){
var results = [];
- exports.forEachSeries(arr, function(x, callback){
+ eachfn(arr, function(x, callback){
iterator(x, function(err, v){
results.push(v);
callback(err);
@@ -179,20 +61,12 @@ exports.mapSeries = function(arr, iterator, callback){
callback(err, results);
});
};
+exports.map = doParallel(_map);
+exports.mapSeries = doSeries(_map);
-exports.reduce = function(arr, memo, iterator, callback){
- exports.forEach(arr, function(x, callback){
- iterator(memo, x, function(err, v){
- memo = v;
- callback(err);
- });
- }, function(err){
- callback(err, memo);
- });
-};
-exports.reduceSeries = function(arr, memo, iterator, callback){
- exports.forEachSeries(arr, function(x, callback){
+var _reduce = function(eachfn, arr, memo, iterator, callback){
+ eachfn(arr, function(x, callback){
iterator(memo, x, function(err, v){
memo = v;
callback(err);
@@ -201,22 +75,13 @@ exports.reduceSeries = function(arr, memo, iterator, callback){
callback(err, memo);
});
};
+exports.reduce = doParallel(_reduce);
+exports.reduceSeries = doSeries(_reduce);
-exports.filter = function(arr, iterator, callback){
- var results = [];
- exports.forEach(arr, function(x, callback){
- iterator(x, function(v){
- if(v) results.push(x);
- callback();
- });
- }, function(err){
- callback(results);
- });
-};
-exports.filterSeries = function(arr, iterator, callback){
+var _filter = function(eachfn, arr, iterator, callback){
var results = [];
- exports.forEachSeries(arr, function(x, callback){
+ eachfn(arr, function(x, callback){
iterator(x, function(v){
if(v) results.push(x);
callback();
@@ -225,6 +90,9 @@ exports.filterSeries = function(arr, iterator, callback){
callback(results);
});
};
+exports.filter = doParallel(_filter);
+exports.filterSeries = doSeries(_filter);
+
exports.some = function(arr, iterator, main_callback){
exports.forEach(arr, function(x, callback){
@@ -253,3 +121,105 @@ exports.every = function(arr, iterator, main_callback){
main_callback(true);
});
};
+
+
+exports.auto = function(tasks, callback){
+ callback = callback || function(){};
+ var keys = Object.keys(tasks);
+ if(!keys.length) return callback(null);
+
+ var completed = [];
+ var emitter = new events.EventEmitter();
+ emitter.addListener('taskComplete', function(){
+ if(completed.length == keys.length){
+ callback(null);
+ }
+ });
+
+ keys.forEach(function(k){
+ var task = (tasks[k] instanceof Function)? [tasks[k]]: tasks[k];
+ var taskCallback = function(err){
+ if(err){
+ callback(err);
+ // stop subsequent errors hitting the callback multiple times
+ callback = function(){};
+ }
+ else {
+ completed.push(k);
+ emitter.emit('taskComplete');
+ }
+ };
+ var requires = task.slice(0, Math.abs(task.length-1)) || [];
+ var ready = function(){
+ return requires.reduce(function(a,x){
+ return (a && completed.indexOf(x) != -1);
+ }, true);
+ };
+ if(ready()) task[task.length-1](taskCallback);
+ else {
+ var listener = function(){
+ if(ready()){
+ emitter.removeListener('taskComplete', listener);
+ task[task.length-1](taskCallback);
+ }
+ };
+ emitter.addListener('taskComplete', listener);
+ }
+ });
+};
+
+exports.waterfall = function(tasks, callback){
+ callback = callback || function(){};
+ var wrapIterator = function(iterator){
+ return function(err){
+ if(err){
+ callback(err);
+ callback = function(){};
+ }
+ else {
+ var args = Array.prototype.slice.call(arguments, 1);
+ var next = iterator.next();
+ if(next) args.push(wrapIterator(next));
+ else args.push(callback);
+ process.nextTick(function(){iterator.apply(null, args)});
+ }
+ };
+ };
+ wrapIterator(exports.iterator(tasks))();
+};
+
+exports.parallel = function(tasks, callback){
+ callback = callback || function(){};
+ exports.map(tasks, function(fn, callback){
+ fn(function(err){
+ var args = Array.prototype.slice.call(arguments,1);
+ if(args.length <= 1) args = args[0];
+ callback.call(null, err, args || null);
+ });
+ }, callback);
+};
+
+exports.series = function(tasks, callback){
+ callback = callback || function(){};
+ exports.mapSeries(tasks, function(fn, callback){
+ fn(function(err){
+ var args = Array.prototype.slice.call(arguments,1);
+ if(args.length <= 1) args = args[0];
+ callback.call(null, err, args || null);
+ });
+ }, callback);
+};
+
+exports.iterator = function(tasks){
+ var makeCallback = function(index){
+ var fn = function(){
+ tasks[index].apply(null, arguments);
+ return fn.next();
+ }
+ fn.next = function(){
+ return (index < tasks.length-1)? makeCallback(index+1): undefined;
+ }
+ return fn;
+ };
+ return makeCallback(0);
+};
Oops, something went wrong.

0 comments on commit cf648d7

Please sign in to comment.