Skip to content

Commit fbeab9b

Browse files
committed
Merge pull request #637 from vergenzt/auto-concurrency
Add concurrency argument to async.auto
2 parents 56bdb50 + f801c68 commit fbeab9b

File tree

3 files changed

+41
-3
lines changed

3 files changed

+41
-3
lines changed

README.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -1256,7 +1256,7 @@ cargo.push({name: 'baz'}, function (err) {
12561256
---------------------------------------
12571257
12581258
<a name="auto" />
1259-
### auto(tasks, [callback])
1259+
### auto(tasks, [callback], [concurrency])
12601260
12611261
Determines the best order for running the functions in `tasks`, based on their requirements. Each function can optionally depend on other functions being completed first, and each function is run as soon as its requirements are satisfied.
12621262
@@ -1307,6 +1307,8 @@ __Arguments__
13071307
pass an error to their callback. Results are always returned; however, if
13081308
an error occurs, no further `tasks` will be performed, and the results
13091309
object will only contain partial results.
1310+
* `concurrency` - An `integer` for determining the maximum number of tasks that
1311+
can be run in parallel. By default, as many as possible.
13101312
13111313
13121314
__Example__

lib/async.js

+9-2
Original file line numberDiff line numberDiff line change
@@ -509,15 +509,19 @@
509509
}
510510
};
511511

512-
async.auto = function (tasks, callback) {
512+
async.auto = function (tasks, callback, concurrency) {
513513
callback = _once(callback || noop);
514514
var keys = _keys(tasks);
515515
var remainingTasks = keys.length;
516516
if (!remainingTasks) {
517517
return callback(null);
518518
}
519+
if (!concurrency) {
520+
concurrency = remainingTasks;
521+
}
519522

520523
var results = {};
524+
var runningTasks = 0;
521525

522526
var listeners = [];
523527
function addListener(fn) {
@@ -543,6 +547,7 @@
543547
_arrayEach(keys, function (k) {
544548
var task = _isArray(tasks[k]) ? tasks[k]: [tasks[k]];
545549
var taskCallback = _restParam(function(err, args) {
550+
runningTasks--;
546551
if (args.length <= 1) {
547552
args = args[0];
548553
}
@@ -572,18 +577,20 @@
572577
}
573578
}
574579
function ready() {
575-
return _reduce(requires, function (a, x) {
580+
return runningTasks < concurrency && _reduce(requires, function (a, x) {
576581
return (a && results.hasOwnProperty(x));
577582
}, true) && !results.hasOwnProperty(k);
578583
}
579584
if (ready()) {
585+
runningTasks++;
580586
task[task.length - 1](taskCallback, results);
581587
}
582588
else {
583589
addListener(listener);
584590
}
585591
function listener() {
586592
if (ready()) {
593+
runningTasks++;
587594
removeListener(listener);
588595
task[task.length - 1](taskCallback, results);
589596
}

test/test-async.js

+29
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,35 @@ exports['auto'] = function(test){
331331
});
332332
};
333333

334+
exports['auto concurrency'] = function (test) {
335+
var concurrency = 2;
336+
var runningTasks = [];
337+
var makeCallback = function(taskName) {
338+
return function(callback) {
339+
runningTasks.push(taskName);
340+
setTimeout(function(){
341+
// Each task returns the array of running tasks as results.
342+
var result = runningTasks.slice(0);
343+
runningTasks.splice(runningTasks.indexOf(taskName), 1);
344+
callback(null, result);
345+
});
346+
};
347+
};
348+
async.auto({
349+
task1: ['task2', makeCallback('task1')],
350+
task2: makeCallback('task2'),
351+
task3: ['task2', makeCallback('task3')],
352+
task4: ['task1', 'task2', makeCallback('task4')],
353+
task5: ['task2', makeCallback('task5')],
354+
task6: ['task2', makeCallback('task6')]
355+
}, function(err, results){
356+
Object.keys(results).forEach(function(taskName) {
357+
test.ok(results[taskName].length <= concurrency);
358+
});
359+
test.done();
360+
}, concurrency);
361+
};
362+
334363
exports['auto petrify'] = function (test) {
335364
var callOrder = [];
336365
async.auto({

0 commit comments

Comments
 (0)