From 90c80a15f3f49bfa75880a6c724d4aceccb9ea4a Mon Sep 17 00:00:00 2001 From: indexzero Date: Sun, 12 Jun 2011 19:39:41 -0400 Subject: [PATCH] [api test] Added `async.forEachLimit()` and associated tests --- lib/async.js | 36 +++++++++++++++++++++++++++++++ test/test-async.js | 53 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+) diff --git a/lib/async.js b/lib/async.js index 67de211b1..b0f993774 100644 --- a/lib/async.js +++ b/lib/async.js @@ -133,6 +133,42 @@ }; iterate(); }; + + async.forEachLimit = function (arr, limit, iterator, callback) { + if (!arr.length || limit <= 0) { + return callback(); + } + var completed = 0; + var started = 0; + var running = 0; + + (function replenish () { + if (completed === arr.length) { + return callback(); + } + + while (running < limit && started < arr.length) { + iterator(arr[started], function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + running -= 1; + if (completed === arr.length) { + callback(); + } + else { + replenish(); + } + } + }); + started += 1; + running += 1; + } + })(); + }; var doParallel = function (fn) { diff --git a/test/test-async.js b/test/test-async.js index 4a7f98688..a00866a3d 100644 --- a/test/test-async.js +++ b/test/test-async.js @@ -491,6 +491,59 @@ exports['forEachSeries error'] = function(test){ setTimeout(test.done, 50); }; +exports['forEachLimit'] = function(test){ + var args = []; + var arr = [0,1,2,3,4,5,6,7,8,9]; + async.forEachLimit(arr, 2, function(x,callback){ + setTimeout(function(){ + args.push(x); + callback(); + }, x*5); + }, function(err){ + test.same(args, arr); + test.done(); + }); +}; + +exports['forEachLimit empty array'] = function(test){ + test.expect(1); + async.forEachLimit([], 2, function(x, callback){ + test.ok(false, 'iterator should not be called'); + callback(); + }, function(err){ + test.ok(true, 'should call callback'); + }); + setTimeout(test.done, 25); +}; + +exports['forEachLimit zero limit'] = function(test){ + test.expect(1); + async.forEachLimit([0,1,2,3,4,5], 0, function(x, callback){ + test.ok(false, 'iterator should not be called'); + callback(); + }, function(err){ + test.ok(true, 'should call callback'); + }); + setTimeout(test.done, 25); +}; + +exports['forEachLimit error'] = function(test){ + test.expect(2); + var arr = [0,1,2,3,4,5,6,7,8,9]; + var call_order = []; + + async.forEachLimit(arr, 3, function(x, callback){ + call_order.push(x); + if (x === 2) { + callback('error'); + } + }, function(err){ + test.same(call_order, [0,1,2]); + test.equals(err, 'error'); + }); + setTimeout(test.done, 25); +}; + exports['map'] = function(test){ var call_order = []; async.map([1,3,2], function(x, callback){