|
77 | 77 | ); |
78 | 78 | } |
79 | 79 |
|
80 | | - function _each(coll, iterator) { |
81 | | - return _isArrayLike(coll) ? |
82 | | - _arrayEach(coll, iterator) : |
83 | | - _forEachOf(coll, iterator); |
84 | | - } |
85 | | - |
86 | 80 | function _arrayEach(arr, iterator) { |
87 | 81 | var index = -1, |
88 | 82 | length = arr.length; |
|
230 | 224 | async.eachOf = function (object, iterator, callback) { |
231 | 225 | callback = _once(callback || noop); |
232 | 226 | object = object || []; |
233 | | - var size = _isArrayLike(object) ? object.length : _keys(object).length; |
234 | | - var completed = 0; |
235 | | - if (!size) { |
236 | | - return callback(null); |
237 | | - } |
238 | | - _each(object, function (value, key) { |
| 227 | + |
| 228 | + var iter = _keyIterator(object); |
| 229 | + var key, completed = 0; |
| 230 | + |
| 231 | + while ((key = iter()) != null) { |
| 232 | + completed += 1; |
239 | 233 | iterator(object[key], key, only_once(done)); |
240 | | - }); |
| 234 | + } |
| 235 | + |
| 236 | + if (completed === 0) callback(null); |
| 237 | + |
241 | 238 | function done(err) { |
| 239 | + completed--; |
242 | 240 | if (err) { |
243 | 241 | callback(err); |
244 | 242 | } |
245 | | - else { |
246 | | - completed += 1; |
247 | | - if (completed >= size) { |
248 | | - callback(null); |
249 | | - } |
| 243 | + // Check key is null in case iterator isn't exhausted |
| 244 | + // and done resolved synchronously. |
| 245 | + else if (key === null && completed <= 0) { |
| 246 | + callback(null); |
250 | 247 | } |
251 | 248 | } |
252 | 249 | }; |
|
272 | 269 | return callback(null); |
273 | 270 | } else { |
274 | 271 | if (sync) { |
275 | | - async.nextTick(iterate); |
| 272 | + async.setImmediate(iterate); |
276 | 273 | } else { |
277 | 274 | iterate(); |
278 | 275 | } |
|
353 | 350 |
|
354 | 351 | function _asyncMap(eachfn, arr, iterator, callback) { |
355 | 352 | callback = _once(callback || noop); |
356 | | - var results = []; |
| 353 | + arr = arr || []; |
| 354 | + var results = _isArrayLike(arr) ? [] : {}; |
357 | 355 | eachfn(arr, function (value, index, callback) { |
358 | 356 | iterator(value, function (err, v) { |
359 | 357 | results[index] = v; |
|
379 | 377 | callback(err); |
380 | 378 | }); |
381 | 379 | }, function (err) { |
382 | | - callback(err || null, memo); |
| 380 | + callback(err, memo); |
383 | 381 | }); |
384 | 382 | }; |
385 | 383 |
|
|
389 | 387 | async.reduce(reversed, memo, iterator, callback); |
390 | 388 | }; |
391 | 389 |
|
| 390 | + async.transform = function (arr, memo, iterator, callback) { |
| 391 | + if (arguments.length === 3) { |
| 392 | + callback = iterator; |
| 393 | + iterator = memo; |
| 394 | + memo = _isArray(arr) ? [] : {}; |
| 395 | + } |
| 396 | + |
| 397 | + async.eachOf(arr, function(v, k, cb) { |
| 398 | + iterator(memo, v, k, cb); |
| 399 | + }, function(err) { |
| 400 | + callback(err, memo); |
| 401 | + }); |
| 402 | + }; |
| 403 | + |
392 | 404 | function _filter(eachfn, arr, iterator, callback) { |
393 | 405 | var results = []; |
394 | 406 | eachfn(arr, function (x, index, callback) { |
|
497 | 509 | } |
498 | 510 | }; |
499 | 511 |
|
500 | | - async.auto = function (tasks, callback) { |
| 512 | + async.auto = function (tasks, concurrency, callback) { |
| 513 | + if (!callback) { |
| 514 | + // concurrency is optional, shift the args. |
| 515 | + callback = concurrency; |
| 516 | + concurrency = null; |
| 517 | + } |
501 | 518 | callback = _once(callback || noop); |
502 | 519 | var keys = _keys(tasks); |
503 | 520 | var remainingTasks = keys.length; |
504 | 521 | if (!remainingTasks) { |
505 | 522 | return callback(null); |
506 | 523 | } |
| 524 | + if (!concurrency) { |
| 525 | + concurrency = remainingTasks; |
| 526 | + } |
507 | 527 |
|
508 | 528 | var results = {}; |
| 529 | + var runningTasks = 0; |
509 | 530 |
|
510 | 531 | var listeners = []; |
511 | 532 | function addListener(fn) { |
|
531 | 552 | _arrayEach(keys, function (k) { |
532 | 553 | var task = _isArray(tasks[k]) ? tasks[k]: [tasks[k]]; |
533 | 554 | var taskCallback = _restParam(function(err, args) { |
| 555 | + runningTasks--; |
534 | 556 | if (args.length <= 1) { |
535 | 557 | args = args[0]; |
536 | 558 | } |
|
560 | 582 | } |
561 | 583 | } |
562 | 584 | function ready() { |
563 | | - return _reduce(requires, function (a, x) { |
| 585 | + return runningTasks < concurrency && _reduce(requires, function (a, x) { |
564 | 586 | return (a && results.hasOwnProperty(x)); |
565 | 587 | }, true) && !results.hasOwnProperty(k); |
566 | 588 | } |
567 | 589 | if (ready()) { |
| 590 | + runningTasks++; |
568 | 591 | task[task.length - 1](taskCallback, results); |
569 | 592 | } |
570 | 593 | else { |
571 | 594 | addListener(listener); |
572 | 595 | } |
573 | 596 | function listener() { |
574 | 597 | if (ready()) { |
| 598 | + runningTasks++; |
575 | 599 | removeListener(listener); |
576 | 600 | task[task.length - 1](taskCallback, results); |
577 | 601 | } |
|
1062 | 1086 | var callback = args.pop(); |
1063 | 1087 | var key = hasher.apply(null, args); |
1064 | 1088 | if (key in memo) { |
1065 | | - async.nextTick(function () { |
| 1089 | + async.setImmediate(function () { |
1066 | 1090 | callback.apply(null, memo[key]); |
1067 | 1091 | }); |
1068 | 1092 | } |
|
0 commit comments