diff options
-rw-r--r-- | lib/async.js | 38 | ||||
-rwxr-xr-x | test/test-async.js | 15 |
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({ |