From 13e1d81fc059d8e491397d01c2852b1f23950398 Mon Sep 17 00:00:00 2001 From: Alexander Early Date: Thu, 28 May 2015 00:19:24 -0700 Subject: experimental map changes --- lib/async.js | 53 ++++++++++++++++++++++++++++++----------------------- test/test-async.js | 54 +++++++++++++++++++++++++++++------------------------- 2 files changed, 59 insertions(+), 48 deletions(-) diff --git a/lib/async.js b/lib/async.js index 38f2a4c..e44f29c 100644 --- a/lib/async.js +++ b/lib/async.js @@ -328,19 +328,21 @@ var completed = 0; var started = 0; var running = 0; + var errored = false; (function replenish () { if (completed >= size) { return callback(); } - while (running < limit && started < size) { + while (running < limit && started < size && !errored) { started += 1; running += 1; var key = keys[started - 1]; iterator(obj[key], key, function (err) { if (err) { callback(err); + errored = true; callback = function () {}; } else { @@ -379,38 +381,43 @@ }; } + function doParallelOf(fn) { + return function (obj, iterator, callback) { + return fn(async.eachOf, obj, iterator, callback); + }; + } + function doParallelLimitOf(limit, fn) { + return function (obj, iterator, callback) { + return fn(_eachOfLimit(limit), obj, iterator, callback); + }; + } + function doSeriesOf(fn) { + return function (obj, iterator, callback) { + return fn(async.eachOfSeries, obj, iterator, callback); + }; + } function _asyncMap(eachfn, arr, iterator, callback) { - arr = _map(arr, function (x, i) { - return {index: i, value: x}; - }); - if (!callback) { - eachfn(arr, function (x, callback) { - iterator(x.value, function (err) { - callback(err); - }); - }); - } else { - var results = []; - eachfn(arr, function (x, callback) { - iterator(x.value, function (err, v) { - results[x.index] = v; - callback(err); - }); - }, function (err) { - callback(err, results); + callback = callback || noop; + var results = []; + eachfn(arr, function (value, index, callback) { + iterator(value, function (err, v) { + results[index] = v; + callback(err); }); - } + }, function (err) { + callback(err, results); + }); } - async.map = doParallel(_asyncMap); - async.mapSeries = doSeries(_asyncMap); + async.map = doParallelOf(_asyncMap); + async.mapSeries = doSeriesOf(_asyncMap); async.mapLimit = function (arr, limit, iterator, callback) { return _mapLimit(limit)(arr, iterator, callback); }; function _mapLimit(limit) { - return doParallelLimit(limit, _asyncMap); + return doParallelLimitOf(limit, _asyncMap); } // reduce only has a series version, as doing reduce in parallel won't diff --git a/test/test-async.js b/test/test-async.js index eba90e9..b3b84fe 100755 --- a/test/test-async.js +++ b/test/test-async.js @@ -1617,7 +1617,9 @@ exports['forEachOfLimit with array'] = function(test){ }); }; -exports['map'] = function(test){ +exports['map'] = { + +'basic': function(test){ var call_order = []; async.map([1,3,2], mapIterator.bind(this, call_order), function(err, results){ test.ok(err === null, err + " passed instead of 'null'"); @@ -1625,9 +1627,9 @@ exports['map'] = function(test){ test.same(results, [2,6,4]); test.done(); }); -}; +}, -exports['map original untouched'] = function(test){ +'map original untouched': function(test){ var a = [1,2,3]; async.map(a, function(x, callback){ callback(null, x*2); @@ -1636,9 +1638,9 @@ exports['map original untouched'] = function(test){ test.same(a, [1,2,3]); test.done(); }); -}; +}, -exports['map without main callback'] = function(test){ +'map without main callback': function(test){ var a = [1,2,3]; var r = []; async.map(a, function(x, callback){ @@ -1649,9 +1651,9 @@ exports['map without main callback'] = function(test){ test.done(); } }); -}; +}, -exports['map error'] = function(test){ +'map error': function(test){ test.expect(1); async.map([1,2,3], function(x, callback){ callback('error'); @@ -1659,9 +1661,9 @@ exports['map error'] = function(test){ test.equals(err, 'error'); }); setTimeout(test.done, 50); -}; +}, -exports['mapSeries'] = function(test){ +'mapSeries': function(test){ var call_order = []; async.mapSeries([1,3,2], mapIterator.bind(this, call_order), function(err, results){ test.ok(err === null, err + " passed instead of 'null'"); @@ -1669,9 +1671,9 @@ exports['mapSeries'] = function(test){ test.same(results, [2,6,4]); test.done(); }); -}; +}, -exports['mapSeries error'] = function(test){ +'mapSeries error': function(test){ test.expect(1); async.mapSeries([1,2,3], function(x, callback){ callback('error'); @@ -1679,10 +1681,10 @@ exports['mapSeries error'] = function(test){ test.equals(err, 'error'); }); setTimeout(test.done, 50); -}; +}, -exports['mapLimit'] = function(test){ +'mapLimit': function(test){ var call_order = []; async.mapLimit([2,4,3], 2, mapIterator.bind(this, call_order), function(err, results){ test.ok(err === null, err + " passed instead of 'null'"); @@ -1690,9 +1692,9 @@ exports['mapLimit'] = function(test){ test.same(results, [4,8,6]); test.done(); }); -}; +}, -exports['mapLimit empty array'] = function(test){ +'mapLimit empty array': function(test){ test.expect(1); async.mapLimit([], 2, function(x, callback){ test.ok(false, 'iterator should not be called'); @@ -1701,27 +1703,27 @@ exports['mapLimit empty array'] = function(test){ test.ok(true, 'should call callback'); }); setTimeout(test.done, 25); -}; +}, -exports['mapLimit limit exceeds size'] = function(test){ +'mapLimit limit exceeds size': function(test){ var call_order = []; async.mapLimit([0,1,2,3,4,5,6,7,8,9], 20, mapIterator.bind(this, call_order), function(err, results){ test.same(call_order, [0,1,2,3,4,5,6,7,8,9]); test.same(results, [0,2,4,6,8,10,12,14,16,18]); test.done(); }); -}; +}, -exports['mapLimit limit equal size'] = function(test){ +'mapLimit limit equal size': function(test){ var call_order = []; async.mapLimit([0,1,2,3,4,5,6,7,8,9], 10, mapIterator.bind(this, call_order), function(err, results){ test.same(call_order, [0,1,2,3,4,5,6,7,8,9]); test.same(results, [0,2,4,6,8,10,12,14,16,18]); test.done(); }); -}; +}, -exports['mapLimit zero limit'] = function(test){ +'mapLimit zero limit': function(test){ test.expect(2); async.mapLimit([0,1,2,3,4,5], 0, function(x, callback){ test.ok(false, 'iterator should not be called'); @@ -1731,9 +1733,9 @@ exports['mapLimit zero limit'] = function(test){ test.ok(true, 'should call callback'); }); setTimeout(test.done, 25); -}; +}, -exports['mapLimit error'] = function(test){ +'mapLimit error': function(test){ test.expect(2); var arr = [0,1,2,3,4,5,6,7,8,9]; var call_order = []; @@ -1748,9 +1750,9 @@ exports['mapLimit error'] = function(test){ test.equals(err, 'error'); }); setTimeout(test.done, 25); -}; +}, -exports['mapLimit does not continue replenishing after error'] = function (test) { +'mapLimit does not continue replenishing after error': function (test) { var started = 0; var arr = [0,1,2,3,4,5,6,7,8,9]; var delay = 10; @@ -1771,6 +1773,8 @@ exports['mapLimit does not continue replenishing after error'] = function (test) test.equal(started, 3); test.done(); }, maxTime); +} + }; -- cgit v1.2.1