diff options
| author | Caolan McMahon <caolan@caolanmcmahon.com> | 2010-06-09 22:53:38 +0100 |
|---|---|---|
| committer | Caolan McMahon <caolan@caolanmcmahon.com> | 2010-06-09 22:53:38 +0100 |
| commit | a57d319468960d4e56ff10cc032212976b7cb849 (patch) | |
| tree | 08536137e957fcf99eaa20c693a9e5b5e68c1a12 | |
| parent | ea4c476560a87d4b665387dbb1d056a8f679f1be (diff) | |
| download | async-a57d319468960d4e56ff10cc032212976b7cb849.tar.gz | |
ensure map and filter results stay in the same order when processing in parallel
| -rw-r--r-- | README.md | 17 | ||||
| -rw-r--r-- | lib/async.js | 18 | ||||
| -rw-r--r-- | test/test-async.js | 46 |
3 files changed, 58 insertions, 23 deletions
@@ -99,9 +99,8 @@ error to this callback, the main callback for the map function is immediately called with the error. Note, that since this function applies the iterator to each item in parallel -there is no guarantee that the iterator functions will complete in order. The -results array can be in a different order to the source array. If you need the -order to be the same, then use mapSeries instead. +there is no guarantee that the iterator functions will complete in order, however +the results array will be in the same order as the original array. __Arguments__ @@ -123,8 +122,7 @@ __Example__ The same as map only the iterator is applied to each item in the array in series. The next iterator is only called once the current one has completed -processing, meaning the results array will be in the same order as the -original. +processing. The results array will be in the same order as the original. ### filter(arr, iterator, callback) @@ -133,7 +131,7 @@ Returns a new array of all the values which pass an async truth test. _The callback for each iterator call only accepts a single argument of true or false, it does not accept an error argument first!_ This is inline with the way node libraries work with truth tests like path.exists. This operation is -performed in parallel, so the results array may be in a different order to the +performed in parallel, but the results array will be in the same order as the original. __Arguments__ @@ -154,8 +152,7 @@ __Example__ The same as filter only the iterator is applied to each item in the array in series. The next iterator is only called once the current one has completed -processing, meaning the results array will be in the same order as the -original. +processing. The results array will be in the same order as the original. ### reduce(arr, memo, iterator, callback) @@ -370,10 +367,10 @@ __Example__ write_file: ['get_data', 'make_folder', function(callback){ // once there is some data and the directory exists, // write the data to a file in the directory - }, + }], email_link: ['write_file', function(callback){ // once the file is written let's email a link to it... - } + }] }); This is a fairly trivial example, but to do this using the basic parallel and diff --git a/lib/async.js b/lib/async.js index e32d7c8..7f216b1 100644 --- a/lib/async.js +++ b/lib/async.js @@ -52,9 +52,12 @@ var doSeries = function(fn){ var _map = function(eachfn, arr, iterator, callback){ var results = []; + for(var i=0; i<arr.length; i++){ + arr[i] = {index: i, value: arr[i]}; + } eachfn(arr, function(x, callback){ - iterator(x, function(err, v){ - results.push(v); + iterator(x.value, function(err, v){ + results[x.index] = v; callback(err); }); }, function(err){ @@ -81,13 +84,20 @@ exports.reduce = function(arr, memo, iterator, callback){ var _filter = function(eachfn, arr, iterator, callback){ var results = []; + for(var i=0; i<arr.length; i++){ + arr[i] = {index: i, value: arr[i]}; + } eachfn(arr, function(x, callback){ - iterator(x, function(v){ + iterator(x.value, function(v){ if(v) results.push(x); callback(); }); }, function(err){ - callback(results); + callback(results.sort(function(a,b){ + return a.index - b.index; + }).map(function(x){ + return x.value; + })); }); }; exports.filter = doParallel(_filter); diff --git a/test/test-async.js b/test/test-async.js index c7da60b..1191305 100644 --- a/test/test-async.js +++ b/test/test-async.js @@ -163,20 +163,31 @@ exports['waterfall multiple callback calls'] = function(test){ exports['parallel'] = function(test){ + var call_order = []; async.parallel([ function(callback){ - setTimeout(function(){callback(null, 1);}, 25); + setTimeout(function(){ + call_order.push(1); + callback(null, 1); + }, 25); }, function(callback){ - setTimeout(function(){callback(null, 2);}, 50); + setTimeout(function(){ + call_order.push(2); + callback(null, 2); + }, 50); }, function(callback){ - setTimeout(function(){callback(null, 3,3);}, 15); + setTimeout(function(){ + call_order.push(3); + callback(null, 3,3); + }, 15); } ], function(err, results){ test.equals(err, null); - test.same(results, [[3,3],1,2]); + test.same(call_order, [3,1,2]); + test.same(results, [1,2,[3,3]]); test.done(); }); }; @@ -204,20 +215,31 @@ exports['parallel no callback'] = function(test){ }; exports['series'] = function(test){ + var call_order = []; async.series([ function(callback){ - setTimeout(function(){callback(null, 1);}, 25); + setTimeout(function(){ + call_order.push(1); + callback(null, 1); + }, 25); }, function(callback){ - setTimeout(function(){callback(null, 2);}, 50); + setTimeout(function(){ + call_order.push(2); + callback(null, 2); + }, 50); }, function(callback){ - setTimeout(function(){callback(null, 3,3);}, 15); + setTimeout(function(){ + call_order.push(3); + callback(null, 3,3); + }, 15); } ], function(err, results){ test.equals(err, null); test.same(results, [1,2,[3,3]]); + test.same(call_order, [1,2,3]); test.done(); }); }; @@ -345,12 +367,15 @@ exports['forEachSeries error'] = function(test){ }; exports['map'] = function(test){ + var call_order = []; async.map([1,3,2], function(x, callback){ setTimeout(function(){ + call_order.push(x); callback(null, x*2); }, x*25); }, function(err, results){ - test.same(results, [2,4,6]); + test.same(call_order, [1,2,3]); + test.same(results, [2,6,4]); test.done(); }); }; @@ -366,11 +391,14 @@ exports['map error'] = function(test){ }; exports['mapSeries'] = function(test){ + var call_order = []; async.mapSeries([1,3,2], function(x, callback){ setTimeout(function(){ + call_order.push(x); callback(null, x*2); }, x*25); }, function(err, results){ + test.same(call_order, [1,3,2]); test.same(results, [2,6,4]); test.done(); }); @@ -418,7 +446,7 @@ exports['filter'] = function(test){ async.filter([3,1,2], function(x, callback){ setTimeout(function(){callback(x % 2);}, x*25); }, function(results){ - test.same(results, [1,3]); + test.same(results, [3,1]); test.done(); }); }; |
