From 49c7fd7d46e50444889dab174a785d87d2b70cd2 Mon Sep 17 00:00:00 2001 From: Calvin French-Owen Date: Tue, 20 Nov 2012 17:44:49 -0800 Subject: Adding mapLimit --- README.md | 29 ++++++++++++++++++++++++++ lib/async.js | 67 ++++++++++++++++++++++++++++++++++++------------------------ 2 files changed, 69 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index 1430894..8c52fd5 100644 --- a/README.md +++ b/README.md @@ -224,6 +224,35 @@ series. The next iterator is only called once the current one has completed processing. The results array will be in the same order as the original. +--------------------------------------- + + +### mapLimit(arr, limit, iterator, callback) + +The same as map only the iterator is applied to batches of items in the +array, in series. The next batch of iterators is only called once the current +one has completed processing. + +__Arguments__ + +* arr - An array to iterate over. +* limit - How many items should be in each batch. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed. + If no error has occured, the callback should be run without arguments or + with an explicit null argument. +* callback(err, results) - A callback which is called after all the iterator + functions have finished, or an error has occurred. Results is an array of the + transformed items from the original array. + +__Example__ + +```js +async.map(['file1','file2','file3'], 1, fs.stat, function(err, results){ + // results is now an array of stats for each file +}); +``` + --------------------------------------- diff --git a/lib/async.js b/lib/async.js index bbbd05c..aeab289 100644 --- a/lib/async.js +++ b/lib/async.js @@ -118,40 +118,48 @@ }; async.forEachLimit = function (arr, limit, iterator, callback) { - callback = callback || function () {}; - if (!arr.length || limit <= 0) { - return callback(); - } - var completed = 0; - var started = 0; - var running = 0; + var fn = forEachLimit(limit); + fn.apply(null, [arr, iterator, callback]); + }; - (function replenish () { - if (completed === arr.length) { + var forEachLimit = function (limit) { + + return function (arr, iterator, callback) { + callback = callback || function () {}; + if (!arr.length || limit <= 0) { return callback(); } + var completed = 0; + var started = 0; + var running = 0; - while (running < limit && started < arr.length) { - started += 1; - running += 1; - iterator(arr[started - 1], function (err) { - if (err) { - callback(err); - callback = function () {}; - } - else { - completed += 1; - running -= 1; - if (completed === arr.length) { - callback(); + (function replenish () { + if (completed === arr.length) { + return callback(); + } + + while (running < limit && started < arr.length) { + started += 1; + running += 1; + iterator(arr[started - 1], function (err) { + if (err) { + callback(err); + callback = function () {}; } else { - replenish(); + completed += 1; + running -= 1; + if (completed === arr.length) { + callback(); + } + else { + replenish(); + } } - } - }); - } - })(); + }); + } + })(); + }; }; @@ -186,6 +194,11 @@ async.map = doParallel(_asyncMap); async.mapSeries = doSeries(_asyncMap); + async.mapLimit = function (arr, limit, iterator, callback) { + var fn = forEachLimit(limit); + return _asyncMap.apply(null, [fn, arr, iterator, callback]); + }; + // reduce only has a series version, as doing reduce in parallel won't // work in many situations. -- cgit v1.2.1