diff --git a/README.md b/README.md index d50da3467..e09b22b9d 100644 --- a/README.md +++ b/README.md @@ -172,8 +172,11 @@ Some functions are also available in the following forms: * [`reduce`](#reduce), [`reduceRight`](#reduceRight) * [`detect`](#detect), `detectSeries` * [`sortBy`](#sortBy) -* [`some`](#some), [`every`](#every) -* [`concat`](#concat), `concatSeries` +* [`some`](#some) +* [`someLimit`](#someLimit) +* [`every`](#every) +* [`concat`](#concat) +* [`concatSeries`](#concatSeries) ### Control Flow @@ -581,6 +584,27 @@ async.some(['file1','file2','file3'], fs.exists, function(result){ --------------------------------------- + +### someLimit(arr, limit iterator, callback) + +__Alias:__ `anyLimit` + +The same as [`some`](#some), only no more than `limit` `iterator`s will be simultaneously +running at any time. + +__Arguments__ + +* `arr` - An array to iterate over. +* `limit` - The maximum number of `iterator`s to run at any time. +* `iterator(item, callback)` - A truth test to apply to each item in the array + in parallel. The iterator is passed a callback(truthValue) which must be + called with a boolean argument once it has completed. +* `callback(result)` - A callback which is called as soon as any iterator returns + `true`, or after all the iterator functions have finished. Result will be + either `true` or `false` depending on the values of the async tests. + +--------------------------------------- + ### every(arr, iterator, [callback]) diff --git a/lib/async.js b/lib/async.js index 8b467eb1a..f0e3adf1e 100644 --- a/lib/async.js +++ b/lib/async.js @@ -456,8 +456,11 @@ async.detectSeries = doSeries(_detect); function _createTester(eachfn, check, defaultValue) { - return function(arr, iterator, main_callback) { - eachfn(arr, function (x, _, callback) { + return function(arr, limit, iterator, main_callback) { + function done() { + main_callback(defaultValue); + } + function iteratee(x, _, callback) { iterator(x, function (v) { if (check(v)) { main_callback(!defaultValue); @@ -465,15 +468,22 @@ } callback(); }); - }, function () { - main_callback(defaultValue); - }); + } + if (arguments.length > 3) { + eachfn(arr, limit, iteratee, done); + } else { + main_callback = iterator; + iterator = limit; + eachfn(arr, iteratee, done); + } }; } async.any = async.some = _createTester(async.eachOf, identity, false); + async.someLimit = _createTester(async.eachOfLimit, identity, false); + async.all = async.every = _createTester(async.eachOf, notId, true); diff --git a/test/test-async.js b/test/test-async.js index 25e964e3f..fe94ddc98 100755 --- a/test/test-async.js +++ b/test/test-async.js @@ -2236,6 +2236,24 @@ exports['some early return'] = function(test){ }, 100); }; +exports['someLimit true'] = function(test){ + async.someLimit([3,1,2], 2, function(x, callback){ + setTimeout(function(){callback(x === 2);}, 0); + }, function(result){ + test.equals(result, true); + test.done(); + }); +}; + +exports['someLimit false'] = function(test){ + async.someLimit([3,1,2], 2, function(x, callback){ + setTimeout(function(){callback(x === 10);}, 0); + }, function(result){ + test.equals(result, false); + test.done(); + }); +}; + exports['any alias'] = function(test){ test.equals(async.any, async.some); test.done();