diff options
author | Caolan McMahon <caolan@caolanmcmahon.com> | 2013-01-31 14:53:25 +0000 |
---|---|---|
committer | Caolan McMahon <caolan@caolanmcmahon.com> | 2013-01-31 14:53:25 +0000 |
commit | 6ad64aca4c04857086f03db7ae8c0fb104e76f95 (patch) | |
tree | 1e8702ab815f158c6523785d7e4abf0247d05870 | |
parent | 48d8cbef98cb6c9c68d6748f0684203a03959135 (diff) | |
download | async-6ad64aca4c04857086f03db7ae8c0fb104e76f95.tar.gz |
automatically call nextTick on some synchronous function calls
-rw-r--r-- | lib/async.js | 53 | ||||
-rw-r--r-- | test/test-async.js | 42 |
2 files changed, 90 insertions, 5 deletions
diff --git a/lib/async.js b/lib/async.js index 0d250ea..71903b3 100644 --- a/lib/async.js +++ b/lib/async.js @@ -118,6 +118,7 @@ } var completed = 0; var iterate = function () { + var sync = true; iterator(arr[completed], function (err) { if (err) { callback(err); @@ -129,10 +130,16 @@ callback(null); } else { - iterate(); + if (sync) { + async.nextTick(iterate); + } + else { + iterate(); + } } } }); + sync = false; }; iterate(); }; @@ -592,12 +599,21 @@ async.whilst = function (test, iterator, callback) { if (test()) { + var sync = true; iterator(function (err) { if (err) { return callback(err); } - async.whilst(test, iterator, callback); + if (sync) { + async.nextTick(function () { + async.whilst(test, iterator, callback); + }); + } + else { + async.whilst(test, iterator, callback); + } }); + sync = false; } else { callback(); @@ -605,27 +621,45 @@ }; async.doWhilst = function (iterator, test, callback) { + var sync = true; iterator(function (err) { if (err) { return callback(err); } if (test()) { - async.doWhilst(iterator, test, callback); + if (sync) { + async.nextTick(function () { + async.doWhilst(iterator, test, callback); + }); + } + else { + async.doWhilst(iterator, test, callback); + } } else { callback(); } }); + sync = false; }; async.until = function (test, iterator, callback) { if (!test()) { + var sync = true; iterator(function (err) { if (err) { return callback(err); } - async.until(test, iterator, callback); + if (sync) { + async.nextTick(function () { + async.until(test, iterator, callback); + }); + } + else { + async.until(test, iterator, callback); + } }); + sync = false; } else { callback(); @@ -633,17 +667,26 @@ }; async.doUntil = function (iterator, test, callback) { + var sync = true; iterator(function (err) { if (err) { return callback(err); } if (!test()) { - async.doUntil(iterator, test, callback); + if (sync) { + async.nextTick(function () { + async.doUntil(iterator, test, callback); + }); + } + else { + async.doUntil(iterator, test, callback); + } } else { callback(); } }); + sync = false; }; async.queue = function (worker, concurrency) { diff --git a/test/test-async.js b/test/test-async.js index 6f2b975..e369f0c 100644 --- a/test/test-async.js +++ b/test/test-async.js @@ -2026,3 +2026,45 @@ exports['queue events'] = function(test) { q.push('poo', function () {calls.push('poo cb');}); q.push('moo', function () {calls.push('moo cb');}); }; + +exports['avoid stack overflows for sync tasks'] = function (test) { + var arr = []; + var funcarr = []; + for (var i = 0; i < 100000; i++) { + arr.push[i]; + funcarr.push(function (cb) { return cb(); }); + } + var iter = function (i, cb) { cb(); }; + var counter = 0; + var pred1 = function () { + return counter <= 100000; + }; + var iter = function (cb) { + counter++; + cb(); + }; + var pred2 = function () { + return counter > 100000; + }; + var resetCounter = function (cb) { + counter = 0; + cb(); + } + async.series([ + async.apply(async.forEach, arr, iter), + async.apply(async.forEachSeries, arr, iter), + async.apply(async.forEachLimit, arr, iter, 2), + async.apply(async.whilst, pred1, iter), + resetCounter, + async.apply(async.until, pred2, iter), + resetCounter, + async.apply(async.doWhilst, iter, pred1), + resetCounter, + async.apply(async.doUntil, iter, pred2), + async.apply(async.series, funcarr), + async.apply(async.parallel, funcarr) + ], + function (err) { + test.done(err); + }); +}; |