summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/async.js38
-rwxr-xr-xtest/test-async.js15
2 files changed, 32 insertions, 21 deletions
diff --git a/lib/async.js b/lib/async.js
index 68b9c54..58b11d9 100644
--- a/lib/async.js
+++ b/lib/async.js
@@ -37,7 +37,16 @@
return function() {
if (called) throw new Error("Callback was already called.");
called = true;
- fn.apply(root, arguments);
+ fn.apply(this, arguments);
+ };
+ }
+
+ function _once(fn) {
+ var called = false;
+ return function() {
+ if (called) return;
+ called = true;
+ fn.apply(this, arguments);
};
}
@@ -206,7 +215,7 @@
async.forEachOf =
async.eachOf = function (object, iterator, callback) {
- callback = callback || noop;
+ callback = _once(callback || noop);
object = object || [];
var size = object.length || _keys(object).length;
var completed = 0;
@@ -219,7 +228,6 @@
function done(err) {
if (err) {
callback(err);
- callback = noop;
}
else {
completed += 1;
@@ -232,7 +240,7 @@
async.forEachOfSeries =
async.eachOfSeries = function (obj, iterator, callback) {
- callback = callback || noop;
+ callback = _once(callback || noop);
obj = obj || [];
var nextKey = _keyIterator(obj);
function iterate() {
@@ -244,7 +252,6 @@
iterator(obj[key], key, function (err) {
if (err) {
callback(err);
- callback = noop;
}
else {
if (sync) {
@@ -270,7 +277,7 @@
function _eachOfLimit(limit) {
return function (obj, iterator, callback) {
- callback = callback || noop;
+ callback = _once(callback || noop);
obj = obj || [];
var nextKey = _keyIterator(obj);
if (limit <= 0) {
@@ -282,9 +289,7 @@
(function replenish () {
if (done && running <= 0) {
- callback(null);
- callback = noop;
- return;
+ return callback(null);
}
while (running < limit && !errored) {
@@ -293,7 +298,6 @@
done = true;
if (running <= 0) {
callback(null);
- callback = noop;
}
return;
}
@@ -303,7 +307,6 @@
if (err) {
callback(err);
errored = true;
- callback = noop;
}
else {
replenish();
@@ -504,7 +507,7 @@
};
async.auto = function (tasks, callback) {
- callback = callback || noop;
+ callback = _once(callback || noop);
var keys = _keys(tasks);
var remainingTasks = keys.length;
if (!remainingTasks) {
@@ -534,11 +537,7 @@
addListener(function () {
if (!remainingTasks) {
- var theCallback = callback;
- // prevent final callback from calling itself if it errors
- callback = noop;
-
- theCallback(null, results);
+ callback(null, results);
}
});
@@ -556,8 +555,6 @@
});
safeResults[k] = args;
callback(err, safeResults);
- // stop subsequent errors hitting callback multiple times
- callback = noop;
}
else {
results[k] = args;
@@ -631,7 +628,7 @@
};
async.waterfall = function (tasks, callback) {
- callback = callback || noop;
+ callback = _once(callback || noop);
if (!_isArray(tasks)) {
var err = new Error('First argument to waterfall must be an array of functions');
return callback(err);
@@ -643,7 +640,6 @@
return function (err) {
if (err) {
callback.apply(null, arguments);
- callback = noop;
}
else {
var args = _baseSlice(arguments, 1);
diff --git a/test/test-async.js b/test/test-async.js
index ce2fc8d..2fe11bd 100755
--- a/test/test-async.js
+++ b/test/test-async.js
@@ -596,6 +596,21 @@ exports['auto calls callback multiple times'] = function(test) {
}, 10);
};
+
+exports['auto calls callback multiple times with parallel functions'] = function(test) {
+ test.expect(1);
+ async.auto({
+ task1: function(callback) { setTimeout(callback,0,"err"); },
+ task2: function(callback) { setTimeout(callback,0,"err"); }
+ },
+ // Error throwing final callback. This should only run once
+ function(err) {
+ test.equal(err, "err");
+ test.done();
+ });
+};
+
+
// Issue 462 on github: https://github.com/caolan/async/issues/462
exports['auto modifying results causes final callback to run early'] = function(test) {
async.auto({