async-rails 1.0.2 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8f2f0d5008e172bd87a7dcea946cd29a2e0e9235
4
- data.tar.gz: b52c5f238f50edd12bde0e5c1612b332bae398db
3
+ metadata.gz: 0b75772d99ec34fbeddd4bb669debffbe1a77739
4
+ data.tar.gz: 29fb194713a6d44c72f620f47babc381a7cf9d63
5
5
  SHA512:
6
- metadata.gz: e99ba2afc03e64eec2378082145aefcd585e56b92d4118788f1c7541df60b0eb0b8605ce7ae62ca55a114934776a785d46cecb9645ba4168d9ea3211854fc475
7
- data.tar.gz: 1b13b2f9dc0b83fe726162441e26d4d00491ca67c93d2298dc5df9d40278579477522032b3171ce020ba9a56d120bc34418c6a383fe439e318038f49a6c0cf07
6
+ metadata.gz: b815f5630a1a01ca09d37bdde7e882c783ab7a04162227ea401c6a168cd02a5b13adc7f2412f1448d965743c91d02cf8f597085a1f6131c635fa55722d9977a9
7
+ data.tar.gz: 0bb53625bab9d1cc06b384f915049684827ce286bc2eb2b369cad70d5ee0660af79a9d90e520bb4964acdad1fccc47993ee988b88dafee03445127bd5661724f
@@ -1,5 +1,5 @@
1
1
  module Async
2
2
  module Rails
3
- VERSION = "1.0.2"
3
+ VERSION = "1.1.0"
4
4
  end
5
5
  end
@@ -8,7 +8,7 @@
8
8
  (function () {
9
9
 
10
10
  var async = {};
11
- var noop = function () {};
11
+ function noop() {}
12
12
 
13
13
  // global on the server, window in the browser
14
14
  var root, previous_async;
@@ -37,7 +37,16 @@
37
37
  return function() {
38
38
  if (called) throw new Error("Callback was already called.");
39
39
  called = true;
40
- fn.apply(root, arguments);
40
+ fn.apply(this, arguments);
41
+ };
42
+ }
43
+
44
+ function _once(fn) {
45
+ var called = false;
46
+ return function() {
47
+ if (called) return;
48
+ called = true;
49
+ fn.apply(this, arguments);
41
50
  };
42
51
  }
43
52
 
@@ -49,16 +58,31 @@
49
58
  return _toString.call(obj) === '[object Array]';
50
59
  };
51
60
 
52
- var _each = function (arr, iterator) {
61
+ function _isArrayLike(arr) {
62
+ return _isArray(arr) || (
63
+ // has a positive integer length property
64
+ typeof arr.length === "number" &&
65
+ arr.length >= 0 &&
66
+ arr.length % 1 === 0
67
+ );
68
+ }
69
+
70
+ function _each(coll, iterator) {
71
+ return _isArrayLike(coll) ?
72
+ _arrayEach(coll, iterator) :
73
+ _forEachOf(coll, iterator);
74
+ }
75
+
76
+ function _arrayEach(arr, iterator) {
53
77
  var index = -1,
54
78
  length = arr.length;
55
79
 
56
80
  while (++index < length) {
57
81
  iterator(arr[index], index, arr);
58
82
  }
59
- };
83
+ }
60
84
 
61
- var _map = function (arr, iterator) {
85
+ function _map(arr, iterator) {
62
86
  var index = -1,
63
87
  length = arr.length,
64
88
  result = Array(length);
@@ -67,20 +91,20 @@
67
91
  result[index] = iterator(arr[index], index, arr);
68
92
  }
69
93
  return result;
70
- };
94
+ }
71
95
 
72
- var _reduce = function (arr, iterator, memo) {
73
- _each(arr, function (x, i, a) {
96
+ function _reduce(arr, iterator, memo) {
97
+ _arrayEach(arr, function (x, i, a) {
74
98
  memo = iterator(memo, x, i, a);
75
99
  });
76
100
  return memo;
77
- };
101
+ }
78
102
 
79
- var _forEachOf = function (object, iterator) {
80
- _each(_keys(object), function (key) {
103
+ function _forEachOf(object, iterator) {
104
+ _arrayEach(_keys(object), function (key) {
81
105
  iterator(object[key], key);
82
106
  });
83
- };
107
+ }
84
108
 
85
109
  var _keys = Object.keys || function (obj) {
86
110
  var keys = [];
@@ -92,7 +116,27 @@
92
116
  return keys;
93
117
  };
94
118
 
95
- var _baseSlice = function (arr, start) {
119
+ function _keyIterator(coll) {
120
+ var i = -1;
121
+ var len;
122
+ var keys;
123
+ if (_isArrayLike(coll)) {
124
+ len = coll.length;
125
+ return function next() {
126
+ i++;
127
+ return i < len ? i : null;
128
+ };
129
+ } else {
130
+ keys = _keys(coll);
131
+ len = keys.length;
132
+ return function next() {
133
+ i++;
134
+ return i < len ? keys[i] : null;
135
+ };
136
+ }
137
+ }
138
+
139
+ function _baseSlice(arr, start) {
96
140
  start = start || 0;
97
141
  var index = -1;
98
142
  var length = arr.length;
@@ -107,7 +151,13 @@
107
151
  result[index] = arr[index + start];
108
152
  }
109
153
  return result;
110
- };
154
+ }
155
+
156
+ function _withoutIndex(iterator) {
157
+ return function (value, index, callback) {
158
+ return iterator(value, callback);
159
+ };
160
+ }
111
161
 
112
162
  //// exported async module functions ////
113
163
 
@@ -147,272 +197,172 @@
147
197
  }
148
198
  }
149
199
 
200
+ async.forEach =
150
201
  async.each = function (arr, iterator, callback) {
151
- callback = callback || noop;
152
- if (!arr.length) {
153
- return callback(null);
154
- }
155
- var completed = 0;
156
- _each(arr, function (x) {
157
- iterator(x, only_once(done) );
158
- });
159
- function done(err) {
160
- if (err) {
161
- callback(err);
162
- callback = noop;
163
- }
164
- else {
165
- completed += 1;
166
- if (completed >= arr.length) {
167
- callback(null);
168
- }
169
- }
170
- }
202
+ return async.eachOf(arr, _withoutIndex(iterator), callback);
171
203
  };
172
- async.forEach = async.each;
173
204
 
205
+ async.forEachSeries =
174
206
  async.eachSeries = function (arr, iterator, callback) {
175
- callback = callback || noop;
176
- if (!arr.length) {
177
- return callback(null);
178
- }
179
- var completed = 0;
180
- var iterate = function () {
181
- iterator(arr[completed], function (err) {
182
- if (err) {
183
- callback(err);
184
- callback = noop;
185
- }
186
- else {
187
- completed += 1;
188
- if (completed >= arr.length) {
189
- callback(null);
190
- }
191
- else {
192
- iterate();
193
- }
194
- }
195
- });
196
- };
197
- iterate();
207
+ return async.eachOfSeries(arr, _withoutIndex(iterator), callback);
198
208
  };
199
- async.forEachSeries = async.eachSeries;
200
209
 
201
210
 
211
+ async.forEachLimit =
202
212
  async.eachLimit = function (arr, limit, iterator, callback) {
203
- var fn = _eachLimit(limit);
204
- fn.apply(null, [arr, iterator, callback]);
213
+ return _eachOfLimit(limit)(arr, _withoutIndex(iterator), callback);
205
214
  };
206
- async.forEachLimit = async.eachLimit;
207
-
208
- var _eachLimit = function (limit) {
209
-
210
- return function (arr, iterator, callback) {
211
- callback = callback || noop;
212
- if (!arr.length || limit <= 0) {
213
- return callback(null);
214
- }
215
- var completed = 0;
216
- var started = 0;
217
- var running = 0;
218
- var errored = false;
219
215
 
220
- (function replenish () {
221
- if (completed >= arr.length) {
222
- return callback(null);
223
- }
224
-
225
- while (running < limit && started < arr.length && !errored) {
226
- started += 1;
227
- running += 1;
228
- iterator(arr[started - 1], function (err) {
229
- if (err) {
230
- callback(err);
231
- errored = true;
232
- callback = noop;
233
- }
234
- else {
235
- completed += 1;
236
- running -= 1;
237
- if (completed >= arr.length) {
238
- callback(null);
239
- }
240
- else {
241
- replenish();
242
- }
243
- }
244
- });
245
- }
246
- })();
247
- };
248
- };
249
-
250
-
251
-
252
- async.forEachOf = async.eachOf = function (object, iterator, callback) {
253
- callback = callback || function () {};
216
+ async.forEachOf =
217
+ async.eachOf = function (object, iterator, callback) {
218
+ callback = _once(callback || noop);
219
+ object = object || [];
254
220
  var size = object.length || _keys(object).length;
255
221
  var completed = 0;
256
222
  if (!size) {
257
223
  return callback(null);
258
224
  }
259
- _forEachOf(object, function (value, key) {
260
- iterator(object[key], key, function (err) {
261
- if (err) {
262
- callback(err);
263
- callback = function () {};
264
- } else {
265
- completed += 1;
266
- if (completed === size) {
267
- callback(null);
268
- }
269
- }
270
- });
225
+ _each(object, function (value, key) {
226
+ iterator(object[key], key, only_once(done));
271
227
  });
228
+ function done(err) {
229
+ if (err) {
230
+ callback(err);
231
+ }
232
+ else {
233
+ completed += 1;
234
+ if (completed >= size) {
235
+ callback(null);
236
+ }
237
+ }
238
+ }
272
239
  };
273
240
 
274
- async.forEachOfSeries = async.eachOfSeries = function (obj, iterator, callback) {
275
- callback = callback || function () {};
276
- var keys = _keys(obj);
277
- var size = keys.length;
278
- if (!size) {
279
- return callback();
280
- }
281
- var completed = 0;
282
- var iterate = function () {
241
+ async.forEachOfSeries =
242
+ async.eachOfSeries = function (obj, iterator, callback) {
243
+ callback = _once(callback || noop);
244
+ obj = obj || [];
245
+ var nextKey = _keyIterator(obj);
246
+ function iterate() {
283
247
  var sync = true;
284
- var key = keys[completed];
248
+ var key = nextKey();
249
+ if (key === null) {
250
+ return callback(null);
251
+ }
285
252
  iterator(obj[key], key, function (err) {
286
253
  if (err) {
287
254
  callback(err);
288
- callback = function () {};
289
255
  }
290
256
  else {
291
- completed += 1;
292
- if (completed >= size) {
293
- callback(null);
257
+ if (sync) {
258
+ async.nextTick(iterate);
294
259
  }
295
260
  else {
296
- if (sync) {
297
- async.nextTick(iterate);
298
- }
299
- else {
300
- iterate();
301
- }
261
+ iterate();
302
262
  }
303
263
  }
304
264
  });
305
265
  sync = false;
306
- };
266
+ }
307
267
  iterate();
308
268
  };
309
269
 
310
270
 
311
271
 
312
- async.forEachOfLimit = async.eachOfLimit = function (obj, limit, iterator, callback) {
313
- _forEachOfLimit(limit)(obj, iterator, callback);
272
+ async.forEachOfLimit =
273
+ async.eachOfLimit = function (obj, limit, iterator, callback) {
274
+ _eachOfLimit(limit)(obj, iterator, callback);
314
275
  };
315
276
 
316
- var _forEachOfLimit = function (limit) {
277
+ function _eachOfLimit(limit) {
317
278
 
318
279
  return function (obj, iterator, callback) {
319
- callback = callback || function () {};
320
- var keys = _keys(obj);
321
- var size = keys.length;
322
- if (!size || limit <= 0) {
280
+ callback = _once(callback || noop);
281
+ obj = obj || [];
282
+ var nextKey = _keyIterator(obj);
283
+ if (limit <= 0) {
323
284
  return callback(null);
324
285
  }
325
- var completed = 0;
326
- var started = 0;
286
+ var done = false;
327
287
  var running = 0;
288
+ var errored = false;
328
289
 
329
290
  (function replenish () {
330
- if (completed >= size) {
331
- return callback();
291
+ if (done && running <= 0) {
292
+ return callback(null);
332
293
  }
333
294
 
334
- while (running < limit && started < size) {
335
- started += 1;
295
+ while (running < limit && !errored) {
296
+ var key = nextKey();
297
+ if (key === null) {
298
+ done = true;
299
+ if (running <= 0) {
300
+ callback(null);
301
+ }
302
+ return;
303
+ }
336
304
  running += 1;
337
- var key = keys[started - 1];
338
305
  iterator(obj[key], key, function (err) {
306
+ running -= 1;
339
307
  if (err) {
340
308
  callback(err);
341
- callback = function () {};
309
+ errored = true;
342
310
  }
343
311
  else {
344
- completed += 1;
345
- running -= 1;
346
- if (completed >= size) {
347
- callback(null);
348
- }
349
- else {
350
- replenish();
351
- }
312
+ replenish();
352
313
  }
353
314
  });
354
315
  }
355
316
  })();
356
317
  };
357
- };
318
+ }
358
319
 
359
320
 
360
- var doParallel = function (fn) {
361
- return function () {
362
- var args = _baseSlice(arguments);
363
- return fn.apply(null, [async.each].concat(args));
321
+ function doParallel(fn) {
322
+ return function (obj, iterator, callback) {
323
+ return fn(async.eachOf, obj, iterator, callback);
364
324
  };
365
- };
366
- var doParallelLimit = function(limit, fn) {
367
- return function () {
368
- var args = _baseSlice(arguments);
369
- return fn.apply(null, [_eachLimit(limit)].concat(args));
325
+ }
326
+ function doParallelLimit(limit, fn) {
327
+ return function (obj, iterator, callback) {
328
+ return fn(_eachOfLimit(limit), obj, iterator, callback);
370
329
  };
371
- };
372
- var doSeries = function (fn) {
373
- return function () {
374
- var args = _baseSlice(arguments);
375
- return fn.apply(null, [async.eachSeries].concat(args));
330
+ }
331
+ function doSeries(fn) {
332
+ return function (obj, iterator, callback) {
333
+ return fn(async.eachOfSeries, obj, iterator, callback);
376
334
  };
377
- };
378
-
335
+ }
379
336
 
380
- var _asyncMap = function (eachfn, arr, iterator, callback) {
381
- arr = _map(arr, function (x, i) {
382
- return {index: i, value: x};
383
- });
384
- if (!callback) {
385
- eachfn(arr, function (x, callback) {
386
- iterator(x.value, function (err) {
387
- callback(err);
388
- });
389
- });
390
- } else {
391
- var results = [];
392
- eachfn(arr, function (x, callback) {
393
- iterator(x.value, function (err, v) {
394
- results[x.index] = v;
395
- callback(err);
396
- });
397
- }, function (err) {
398
- callback(err, results);
337
+ function _asyncMap(eachfn, arr, iterator, callback) {
338
+ callback = _once(callback || noop);
339
+ var results = [];
340
+ eachfn(arr, function (value, index, callback) {
341
+ iterator(value, function (err, v) {
342
+ results[index] = v;
343
+ callback(err);
399
344
  });
400
- }
401
- };
345
+ }, function (err) {
346
+ callback(err, results);
347
+ });
348
+ }
349
+
402
350
  async.map = doParallel(_asyncMap);
403
351
  async.mapSeries = doSeries(_asyncMap);
404
352
  async.mapLimit = function (arr, limit, iterator, callback) {
405
353
  return _mapLimit(limit)(arr, iterator, callback);
406
354
  };
407
355
 
408
- var _mapLimit = function(limit) {
356
+ function _mapLimit(limit) {
409
357
  return doParallelLimit(limit, _asyncMap);
410
- };
358
+ }
411
359
 
412
360
  // reduce only has a series version, as doing reduce in parallel won't
413
361
  // work in many situations.
362
+ async.inject =
363
+ async.foldl =
414
364
  async.reduce = function (arr, memo, iterator, callback) {
415
- async.eachSeries(arr, function (x, callback) {
365
+ async.eachOfSeries(arr, function (x, i, callback) {
416
366
  iterator(memo, x, function (err, v) {
417
367
  memo = v;
418
368
  callback(err);
@@ -421,71 +371,67 @@
421
371
  callback(err || null, memo);
422
372
  });
423
373
  };
424
- // inject alias
425
- async.inject = async.reduce;
426
- // foldl alias
427
- async.foldl = async.reduce;
428
374
 
375
+ async.foldr =
429
376
  async.reduceRight = function (arr, memo, iterator, callback) {
430
377
  var reversed = _map(arr, function (x) {
431
378
  return x;
432
379
  }).reverse();
433
380
  async.reduce(reversed, memo, iterator, callback);
434
381
  };
435
- // foldr alias
436
- async.foldr = async.reduceRight;
437
382
 
438
- var _filter = function (eachfn, arr, iterator, callback) {
383
+ function _filter(eachfn, arr, iterator, callback) {
439
384
  var results = [];
440
385
  arr = _map(arr, function (x, i) {
441
386
  return {index: i, value: x};
442
387
  });
443
- eachfn(arr, function (x, callback) {
388
+ eachfn(arr, function (x, index, callback) {
444
389
  iterator(x.value, function (v) {
445
390
  if (v) {
446
391
  results.push(x);
447
392
  }
448
393
  callback();
449
394
  });
450
- }, function (err) {
395
+ }, function () {
451
396
  callback(_map(results.sort(function (a, b) {
452
397
  return a.index - b.index;
453
398
  }), function (x) {
454
399
  return x.value;
455
400
  }));
456
401
  });
457
- };
402
+ }
403
+
404
+ async.select =
458
405
  async.filter = doParallel(_filter);
406
+
407
+ async.selectSeries =
459
408
  async.filterSeries = doSeries(_filter);
460
- // select alias
461
- async.select = async.filter;
462
- async.selectSeries = async.filterSeries;
463
409
 
464
- var _reject = function (eachfn, arr, iterator, callback) {
410
+ function _reject(eachfn, arr, iterator, callback) {
465
411
  var results = [];
466
412
  arr = _map(arr, function (x, i) {
467
413
  return {index: i, value: x};
468
414
  });
469
- eachfn(arr, function (x, callback) {
415
+ eachfn(arr, function (x, index, callback) {
470
416
  iterator(x.value, function (v) {
471
417
  if (!v) {
472
418
  results.push(x);
473
419
  }
474
420
  callback();
475
421
  });
476
- }, function (err) {
422
+ }, function () {
477
423
  callback(_map(results.sort(function (a, b) {
478
424
  return a.index - b.index;
479
425
  }), function (x) {
480
426
  return x.value;
481
427
  }));
482
428
  });
483
- };
429
+ }
484
430
  async.reject = doParallel(_reject);
485
431
  async.rejectSeries = doSeries(_reject);
486
432
 
487
- var _detect = function (eachfn, arr, iterator, main_callback) {
488
- eachfn(arr, function (x, callback) {
433
+ function _detect(eachfn, arr, iterator, main_callback) {
434
+ eachfn(arr, function (x, index, callback) {
489
435
  iterator(x, function (result) {
490
436
  if (result) {
491
437
  main_callback(x);
@@ -495,15 +441,16 @@
495
441
  callback();
496
442
  }
497
443
  });
498
- }, function (err) {
444
+ }, function () {
499
445
  main_callback();
500
446
  });
501
- };
447
+ }
502
448
  async.detect = doParallel(_detect);
503
449
  async.detectSeries = doSeries(_detect);
504
450
 
451
+ async.any =
505
452
  async.some = function (arr, iterator, main_callback) {
506
- async.each(arr, function (x, callback) {
453
+ async.eachOf(arr, function (x, _, callback) {
507
454
  iterator(x, function (v) {
508
455
  if (v) {
509
456
  main_callback(true);
@@ -511,15 +458,14 @@
511
458
  }
512
459
  callback();
513
460
  });
514
- }, function (err) {
461
+ }, function () {
515
462
  main_callback(false);
516
463
  });
517
464
  };
518
- // any alias
519
- async.any = async.some;
520
465
 
466
+ async.all =
521
467
  async.every = function (arr, iterator, main_callback) {
522
- async.each(arr, function (x, callback) {
468
+ async.eachOf(arr, function (x, _, callback) {
523
469
  iterator(x, function (v) {
524
470
  if (!v) {
525
471
  main_callback(false);
@@ -527,12 +473,10 @@
527
473
  }
528
474
  callback();
529
475
  });
530
- }, function (err) {
476
+ }, function () {
531
477
  main_callback(true);
532
478
  });
533
479
  };
534
- // all alias
535
- async.all = async.every;
536
480
 
537
481
  async.sortBy = function (arr, iterator, callback) {
538
482
  async.map(arr, function (x, callback) {
@@ -549,19 +493,21 @@
549
493
  return callback(err);
550
494
  }
551
495
  else {
552
- var fn = function (left, right) {
553
- var a = left.criteria, b = right.criteria;
554
- return a < b ? -1 : a > b ? 1 : 0;
555
- };
556
- callback(null, _map(results.sort(fn), function (x) {
496
+ callback(null, _map(results.sort(comparator), function (x) {
557
497
  return x.value;
558
498
  }));
559
499
  }
500
+
560
501
  });
502
+
503
+ function comparator(left, right) {
504
+ var a = left.criteria, b = right.criteria;
505
+ return a < b ? -1 : a > b ? 1 : 0;
506
+ }
561
507
  };
562
508
 
563
509
  async.auto = function (tasks, callback) {
564
- callback = callback || noop;
510
+ callback = _once(callback || noop);
565
511
  var keys = _keys(tasks);
566
512
  var remainingTasks = keys.length;
567
513
  if (!remainingTasks) {
@@ -571,56 +517,50 @@
571
517
  var results = {};
572
518
 
573
519
  var listeners = [];
574
- var addListener = function (fn) {
520
+ function addListener(fn) {
575
521
  listeners.unshift(fn);
576
- };
577
- var removeListener = function (fn) {
522
+ }
523
+ function removeListener(fn) {
578
524
  for (var i = 0; i < listeners.length; i += 1) {
579
525
  if (listeners[i] === fn) {
580
526
  listeners.splice(i, 1);
581
527
  return;
582
528
  }
583
529
  }
584
- };
585
- var taskComplete = function () {
530
+ }
531
+ function taskComplete() {
586
532
  remainingTasks--;
587
- _each(listeners.slice(0), function (fn) {
533
+ _arrayEach(listeners.slice(0), function (fn) {
588
534
  fn();
589
535
  });
590
- };
536
+ }
591
537
 
592
538
  addListener(function () {
593
539
  if (!remainingTasks) {
594
- var theCallback = callback;
595
- // prevent final callback from calling itself if it errors
596
- callback = noop;
597
-
598
- theCallback(null, results);
540
+ callback(null, results);
599
541
  }
600
542
  });
601
543
 
602
- _each(keys, function (k) {
544
+ _arrayEach(keys, function (k) {
603
545
  var task = _isArray(tasks[k]) ? tasks[k]: [tasks[k]];
604
- var taskCallback = function (err) {
546
+ function taskCallback(err) {
605
547
  var args = _baseSlice(arguments, 1);
606
548
  if (args.length <= 1) {
607
549
  args = args[0];
608
550
  }
609
551
  if (err) {
610
552
  var safeResults = {};
611
- _each(_keys(results), function(rkey) {
553
+ _arrayEach(_keys(results), function(rkey) {
612
554
  safeResults[rkey] = results[rkey];
613
555
  });
614
556
  safeResults[k] = args;
615
557
  callback(err, safeResults);
616
- // stop subsequent errors hitting callback multiple times
617
- callback = noop;
618
558
  }
619
559
  else {
620
560
  results[k] = args;
621
561
  async.setImmediate(taskComplete);
622
562
  }
623
- };
563
+ }
624
564
  var requires = task.slice(0, Math.abs(task.length - 1)) || [];
625
565
  // prevent dead-locks
626
566
  var len = requires.length;
@@ -633,23 +573,23 @@
633
573
  throw new Error('Has cyclic dependencies');
634
574
  }
635
575
  }
636
- var ready = function () {
576
+ function ready() {
637
577
  return _reduce(requires, function (a, x) {
638
578
  return (a && results.hasOwnProperty(x));
639
579
  }, true) && !results.hasOwnProperty(k);
640
- };
580
+ }
641
581
  if (ready()) {
642
582
  task[task.length - 1](taskCallback, results);
643
583
  }
644
584
  else {
645
- var listener = function () {
646
- if (ready()) {
647
- removeListener(listener);
648
- task[task.length - 1](taskCallback, results);
649
- }
650
- };
651
585
  addListener(listener);
652
586
  }
587
+ function listener() {
588
+ if (ready()) {
589
+ removeListener(listener);
590
+ task[task.length - 1](taskCallback, results);
591
+ }
592
+ }
653
593
  });
654
594
  };
655
595
 
@@ -664,14 +604,16 @@
664
604
  }
665
605
  // Make sure times is a number
666
606
  times = parseInt(times, 10) || DEFAULT_TIMES;
667
- var wrappedTask = function(wrappedCallback, wrappedResults) {
668
- var retryAttempt = function(task, finalAttempt) {
607
+
608
+ function wrappedTask(wrappedCallback, wrappedResults) {
609
+ function retryAttempt(task, finalAttempt) {
669
610
  return function(seriesCallback) {
670
611
  task(function(err, result){
671
612
  seriesCallback(!err || finalAttempt, {err: err, result: result});
672
613
  }, wrappedResults);
673
614
  };
674
- };
615
+ }
616
+
675
617
  while (times) {
676
618
  attempts.push(retryAttempt(task, !(times-=1)));
677
619
  }
@@ -679,13 +621,14 @@
679
621
  data = data[data.length - 1];
680
622
  (wrappedCallback || callback)(data.err, data.result);
681
623
  });
682
- };
624
+ }
625
+
683
626
  // If a callback is passed, run this as a controll flow
684
627
  return callback ? wrappedTask() : wrappedTask;
685
628
  };
686
629
 
687
630
  async.waterfall = function (tasks, callback) {
688
- callback = callback || noop;
631
+ callback = _once(callback || noop);
689
632
  if (!_isArray(tasks)) {
690
633
  var err = new Error('First argument to waterfall must be an array of functions');
691
634
  return callback(err);
@@ -693,11 +636,10 @@
693
636
  if (!tasks.length) {
694
637
  return callback();
695
638
  }
696
- var wrapIterator = function (iterator) {
639
+ function wrapIterator(iterator) {
697
640
  return function (err) {
698
641
  if (err) {
699
642
  callback.apply(null, arguments);
700
- callback = noop;
701
643
  }
702
644
  else {
703
645
  var args = _baseSlice(arguments, 1);
@@ -708,100 +650,70 @@
708
650
  else {
709
651
  args.push(callback);
710
652
  }
711
- async.setImmediate(function () {
712
- iterator.apply(null, args);
713
- });
653
+ ensureAsync(iterator).apply(null, args);
714
654
  }
715
655
  };
716
- };
656
+ }
717
657
  wrapIterator(async.iterator(tasks))();
718
658
  };
719
659
 
720
- var _parallel = function(eachfn, tasks, callback) {
660
+ function _parallel(eachfn, tasks, callback) {
721
661
  callback = callback || noop;
722
- if (_isArray(tasks)) {
723
- eachfn.map(tasks, function (fn, callback) {
724
- if (fn) {
725
- fn(function (err) {
726
- var args = _baseSlice(arguments, 1);
727
- if (args.length <= 1) {
728
- args = args[0];
729
- }
730
- callback.call(null, err, args);
731
- });
662
+ var results = _isArrayLike(tasks) ? [] : {};
663
+
664
+ eachfn(tasks, function (task, key, callback) {
665
+ task(function (err) {
666
+ var args = _baseSlice(arguments, 1);
667
+ if (args.length <= 1) {
668
+ args = args[0];
732
669
  }
733
- }, callback);
734
- }
735
- else {
736
- var results = {};
737
- eachfn.each(_keys(tasks), function (k, callback) {
738
- tasks[k](function (err) {
739
- var args = _baseSlice(arguments, 1);
740
- if (args.length <= 1) {
741
- args = args[0];
742
- }
743
- results[k] = args;
744
- callback(err);
745
- });
746
- }, function (err) {
747
- callback(err, results);
670
+ results[key] = args;
671
+ callback(err);
748
672
  });
749
- }
750
- };
673
+ }, function (err) {
674
+ callback(err, results);
675
+ });
676
+ }
751
677
 
752
678
  async.parallel = function (tasks, callback) {
753
- _parallel({ map: async.map, each: async.each }, tasks, callback);
679
+ _parallel(async.eachOf, tasks, callback);
754
680
  };
755
681
 
756
682
  async.parallelLimit = function(tasks, limit, callback) {
757
- _parallel({ map: _mapLimit(limit), each: _eachLimit(limit) }, tasks, callback);
683
+ _parallel(_eachOfLimit(limit), tasks, callback);
758
684
  };
759
685
 
760
686
  async.series = function (tasks, callback) {
761
687
  callback = callback || noop;
762
- if (_isArray(tasks)) {
763
- async.mapSeries(tasks, function (fn, callback) {
764
- if (fn) {
765
- fn(function (err) {
766
- var args = _baseSlice(arguments, 1);
767
- if (args.length <= 1) {
768
- args = args[0];
769
- }
770
- callback.call(null, err, args);
771
- });
688
+ var results = _isArrayLike(tasks) ? [] : {};
689
+
690
+ async.eachOfSeries(tasks, function (task, key, callback) {
691
+ task(function (err) {
692
+ var args = _baseSlice(arguments, 1);
693
+ if (args.length <= 1) {
694
+ args = args[0];
772
695
  }
773
- }, callback);
774
- }
775
- else {
776
- var results = {};
777
- async.eachSeries(_keys(tasks), function (k, callback) {
778
- tasks[k](function (err) {
779
- var args = _baseSlice(arguments, 1);
780
- if (args.length <= 1) {
781
- args = args[0];
782
- }
783
- results[k] = args;
784
- callback(err);
785
- });
786
- }, function (err) {
787
- callback(err, results);
696
+ results[key] = args;
697
+ callback(err);
788
698
  });
789
- }
699
+ }, function (err) {
700
+ callback(err, results);
701
+ });
790
702
  };
791
703
 
792
704
  async.iterator = function (tasks) {
793
- var makeCallback = function (index) {
794
- var fn = function () {
705
+ function makeCallback(index) {
706
+ function fn() {
795
707
  if (tasks.length) {
796
708
  tasks[index].apply(null, arguments);
797
709
  }
798
710
  return fn.next();
799
- };
711
+ }
800
712
  fn.next = function () {
801
713
  return (index < tasks.length - 1) ? makeCallback(index + 1): null;
802
714
  };
803
715
  return fn;
804
- };
716
+ }
805
717
  return makeCallback(0);
806
718
  };
807
719
 
@@ -814,17 +726,17 @@
814
726
  };
815
727
  };
816
728
 
817
- var _concat = function (eachfn, arr, fn, callback) {
818
- var r = [];
819
- eachfn(arr, function (x, cb) {
729
+ function _concat(eachfn, arr, fn, callback) {
730
+ var result = [];
731
+ eachfn(arr, function (x, index, cb) {
820
732
  fn(x, function (err, y) {
821
- r = r.concat(y || []);
733
+ result = result.concat(y || []);
822
734
  cb(err);
823
735
  });
824
736
  }, function (err) {
825
- callback(err, r);
737
+ callback(err, result);
826
738
  });
827
- };
739
+ }
828
740
  async.concat = doParallel(_concat);
829
741
  async.concatSeries = doSeries(_concat);
830
742
 
@@ -886,85 +798,93 @@
886
798
  });
887
799
  };
888
800
 
889
- async.queue = function (worker, concurrency) {
890
- if (concurrency === undefined) {
801
+ function _queue(worker, concurrency, payload) {
802
+ if (concurrency == null) {
891
803
  concurrency = 1;
892
804
  }
893
805
  else if(concurrency === 0) {
894
806
  throw new Error('Concurrency must not be zero');
895
807
  }
896
808
  function _insert(q, data, pos, callback) {
897
- if (!q.started){
809
+ if (callback != null && typeof callback !== "function") {
810
+ throw new Error("task callback must be a function");
811
+ }
898
812
  q.started = true;
899
- }
900
- if (!_isArray(data)) {
901
- data = [data];
902
- }
903
- if(data.length === 0) {
904
- // call drain immediately if there are no tasks
905
- return async.setImmediate(function() {
906
- if (q.drain) {
907
- q.drain();
908
- }
909
- });
910
- }
911
- _each(data, function(task) {
912
- var item = {
913
- data: task,
914
- callback: typeof callback === 'function' ? callback : null
915
- };
916
-
917
- if (pos) {
918
- q.tasks.unshift(item);
919
- } else {
920
- q.tasks.push(item);
921
- }
813
+ if (!_isArray(data)) {
814
+ data = [data];
815
+ }
816
+ if(data.length === 0 && q.idle()) {
817
+ // call drain immediately if there are no tasks
818
+ return async.setImmediate(function() {
819
+ q.drain();
820
+ });
821
+ }
822
+ _arrayEach(data, function(task) {
823
+ var item = {
824
+ data: task,
825
+ callback: callback || noop
826
+ };
922
827
 
923
- if (q.saturated && q.tasks.length === q.concurrency) {
924
- q.saturated();
925
- }
926
- async.setImmediate(q.process);
927
- });
828
+ if (pos) {
829
+ q.tasks.unshift(item);
830
+ } else {
831
+ q.tasks.push(item);
832
+ }
833
+
834
+ if (q.tasks.length === q.concurrency) {
835
+ q.saturated();
836
+ }
837
+ async.setImmediate(q.process);
838
+ });
928
839
  }
929
840
 
930
841
  var workers = 0;
931
842
  var q = {
932
843
  tasks: [],
933
844
  concurrency: concurrency,
934
- saturated: null,
935
- empty: null,
936
- drain: null,
845
+ saturated: noop,
846
+ empty: noop,
847
+ drain: noop,
937
848
  started: false,
938
849
  paused: false,
939
850
  push: function (data, callback) {
940
- _insert(q, data, false, callback);
851
+ _insert(q, data, false, callback);
941
852
  },
942
853
  kill: function () {
943
- q.drain = null;
944
- q.tasks = [];
854
+ q.drain = noop;
855
+ q.tasks = [];
945
856
  },
946
857
  unshift: function (data, callback) {
947
- _insert(q, data, true, callback);
858
+ _insert(q, data, true, callback);
948
859
  },
949
860
  process: function () {
950
861
  if (!q.paused && workers < q.concurrency && q.tasks.length) {
951
- var task = q.tasks.shift();
952
- if (q.empty && q.tasks.length === 0) {
862
+ var tasks = payload ?
863
+ q.tasks.splice(0, payload) :
864
+ q.tasks.splice(0, q.tasks.length);
865
+
866
+ var data = _map(tasks, function (task) {
867
+ return task.data;
868
+ });
869
+
870
+ if (q.tasks.length === 0) {
953
871
  q.empty();
954
872
  }
955
873
  workers += 1;
956
- var next = function () {
957
- workers -= 1;
958
- if (task.callback) {
959
- task.callback.apply(task, arguments);
960
- }
961
- if (q.drain && q.tasks.length + workers === 0) {
962
- q.drain();
963
- }
964
- q.process();
965
- };
966
874
  var cb = only_once(next);
967
- worker(task.data, cb);
875
+ worker(data, cb);
876
+ }
877
+
878
+ function next() {
879
+ workers -= 1;
880
+ var args = arguments;
881
+ _arrayEach(tasks, function (task) {
882
+ task.callback.apply(task, args);
883
+ });
884
+ if (q.tasks.length + workers === 0) {
885
+ q.drain();
886
+ }
887
+ q.process();
968
888
  }
969
889
  },
970
890
  length: function () {
@@ -977,7 +897,6 @@
977
897
  return q.tasks.length + workers === 0;
978
898
  },
979
899
  pause: function () {
980
- if (q.paused === true) { return; }
981
900
  q.paused = true;
982
901
  },
983
902
  resume: function () {
@@ -991,58 +910,65 @@
991
910
  }
992
911
  }
993
912
  };
913
+ return q;
914
+ }
915
+
916
+ async.queue = function (worker, concurrency) {
917
+ var q = _queue(function (items, cb) {
918
+ worker(items[0], cb);
919
+ }, concurrency, 1);
920
+
994
921
  return q;
995
922
  };
996
923
 
997
924
  async.priorityQueue = function (worker, concurrency) {
998
925
 
999
926
  function _compareTasks(a, b){
1000
- return a.priority - b.priority;
927
+ return a.priority - b.priority;
1001
928
  }
1002
929
 
1003
930
  function _binarySearch(sequence, item, compare) {
1004
931
  var beg = -1,
1005
932
  end = sequence.length - 1;
1006
933
  while (beg < end) {
1007
- var mid = beg + ((end - beg + 1) >>> 1);
1008
- if (compare(item, sequence[mid]) >= 0) {
1009
- beg = mid;
1010
- } else {
1011
- end = mid - 1;
1012
- }
934
+ var mid = beg + ((end - beg + 1) >>> 1);
935
+ if (compare(item, sequence[mid]) >= 0) {
936
+ beg = mid;
937
+ } else {
938
+ end = mid - 1;
939
+ }
1013
940
  }
1014
941
  return beg;
1015
942
  }
1016
943
 
1017
944
  function _insert(q, data, priority, callback) {
1018
- if (!q.started){
945
+ if (callback != null && typeof callback !== "function") {
946
+ throw new Error("task callback must be a function");
947
+ }
1019
948
  q.started = true;
1020
- }
1021
- if (!_isArray(data)) {
1022
- data = [data];
1023
- }
1024
- if(data.length === 0) {
1025
- // call drain immediately if there are no tasks
1026
- return async.setImmediate(function() {
1027
- if (q.drain) {
1028
- q.drain();
1029
- }
1030
- });
1031
- }
1032
- _each(data, function(task) {
1033
- var item = {
1034
- data: task,
1035
- priority: priority,
1036
- callback: typeof callback === 'function' ? callback : null
1037
- };
949
+ if (!_isArray(data)) {
950
+ data = [data];
951
+ }
952
+ if(data.length === 0) {
953
+ // call drain immediately if there are no tasks
954
+ return async.setImmediate(function() {
955
+ q.drain();
956
+ });
957
+ }
958
+ _arrayEach(data, function(task) {
959
+ var item = {
960
+ data: task,
961
+ priority: priority,
962
+ callback: typeof callback === 'function' ? callback : noop
963
+ };
1038
964
 
1039
- q.tasks.splice(_binarySearch(q.tasks, item, _compareTasks) + 1, 0, item);
965
+ q.tasks.splice(_binarySearch(q.tasks, item, _compareTasks) + 1, 0, item);
1040
966
 
1041
- if (q.saturated && q.tasks.length === q.concurrency) {
1042
- q.saturated();
1043
- }
1044
- async.setImmediate(q.process);
1045
- });
967
+ if (q.tasks.length === q.concurrency) {
968
+ q.saturated();
969
+ }
970
+ async.setImmediate(q.process);
971
+ });
1046
972
  }
1047
973
 
1048
974
  // Start with a normal queue
@@ -1050,7 +976,7 @@
1050
976
 
1051
977
  // Override push to accept second parameter representing priority
1052
978
  q.push = function (data, priority, callback) {
1053
- _insert(q, data, priority, callback);
979
+ _insert(q, data, priority, callback);
1054
980
  };
1055
981
 
1056
982
  // Remove unshift function
@@ -1060,74 +986,10 @@
1060
986
  };
1061
987
 
1062
988
  async.cargo = function (worker, payload) {
1063
- var working = false,
1064
- tasks = [];
1065
-
1066
- var cargo = {
1067
- tasks: tasks,
1068
- payload: payload,
1069
- saturated: null,
1070
- empty: null,
1071
- drain: null,
1072
- drained: true,
1073
- push: function (data, callback) {
1074
- if (!_isArray(data)) {
1075
- data = [data];
1076
- }
1077
- _each(data, function(task) {
1078
- tasks.push({
1079
- data: task,
1080
- callback: typeof callback === 'function' ? callback : null
1081
- });
1082
- cargo.drained = false;
1083
- if (cargo.saturated && tasks.length === payload) {
1084
- cargo.saturated();
1085
- }
1086
- });
1087
- async.setImmediate(cargo.process);
1088
- },
1089
- process: function process() {
1090
- if (working) return;
1091
- if (tasks.length === 0) {
1092
- if(cargo.drain && !cargo.drained) cargo.drain();
1093
- cargo.drained = true;
1094
- return;
1095
- }
1096
-
1097
- var ts = typeof payload === 'number' ?
1098
- tasks.splice(0, payload) :
1099
- tasks.splice(0, tasks.length);
1100
-
1101
- var ds = _map(ts, function (task) {
1102
- return task.data;
1103
- });
1104
-
1105
- if(cargo.empty) cargo.empty();
1106
- working = true;
1107
- worker(ds, function () {
1108
- working = false;
1109
-
1110
- var args = arguments;
1111
- _each(ts, function (data) {
1112
- if (data.callback) {
1113
- data.callback.apply(null, args);
1114
- }
1115
- });
1116
-
1117
- process();
1118
- });
1119
- },
1120
- length: function () {
1121
- return tasks.length;
1122
- },
1123
- running: function () {
1124
- return working;
1125
- }
1126
- };
1127
- return cargo;
989
+ return _queue(worker, 1, payload);
1128
990
  };
1129
991
 
1130
- var _console_fn = function (name) {
992
+ function _console_fn(name) {
1131
993
  return function (fn) {
1132
994
  var args = _baseSlice(arguments, 1);
1133
995
  fn.apply(null, args.concat([function (err) {
@@ -1139,14 +1001,14 @@
1139
1001
  }
1140
1002
  }
1141
1003
  else if (console[name]) {
1142
- _each(args, function (x) {
1004
+ _arrayEach(args, function (x) {
1143
1005
  console[name](x);
1144
1006
  });
1145
1007
  }
1146
1008
  }
1147
1009
  }]));
1148
1010
  };
1149
- };
1011
+ }
1150
1012
  async.log = _console_fn('log');
1151
1013
  async.dir = _console_fn('dir');
1152
1014
  /*async.info = _console_fn('info');
@@ -1159,7 +1021,7 @@
1159
1021
  hasher = hasher || function (x) {
1160
1022
  return x;
1161
1023
  };
1162
- var memoized = function () {
1024
+ function memoized() {
1163
1025
  var args = _baseSlice(arguments);
1164
1026
  var callback = args.pop();
1165
1027
  var key = hasher.apply(null, args);
@@ -1182,7 +1044,7 @@
1182
1044
  }
1183
1045
  }]));
1184
1046
  }
1185
- };
1047
+ }
1186
1048
  memoized.memo = memo;
1187
1049
  memoized.unmemoized = fn;
1188
1050
  return memoized;
@@ -1215,7 +1077,14 @@
1215
1077
  return function () {
1216
1078
  var that = this;
1217
1079
  var args = _baseSlice(arguments);
1218
- var callback = args.pop();
1080
+
1081
+ var callback = args.slice(-1)[0];
1082
+ if (typeof callback == 'function') {
1083
+ args.pop();
1084
+ } else {
1085
+ callback = noop;
1086
+ }
1087
+
1219
1088
  async.reduce(fns, args, function (newargs, fn, cb) {
1220
1089
  fn.apply(that, newargs.concat([function () {
1221
1090
  var err = arguments[0];
@@ -1233,16 +1102,17 @@
1233
1102
  return async.seq.apply(null, Array.prototype.reverse.call(arguments));
1234
1103
  };
1235
1104
 
1236
- var _applyEach = function (eachfn, fns /*args...*/) {
1237
- var go = function () {
1105
+
1106
+ function _applyEach(eachfn, fns /*args...*/) {
1107
+ function go() {
1238
1108
  var that = this;
1239
1109
  var args = _baseSlice(arguments);
1240
1110
  var callback = args.pop();
1241
- return eachfn(fns, function (fn, cb) {
1111
+ return eachfn(fns, function (fn, _, cb) {
1242
1112
  fn.apply(that, args.concat([cb]));
1243
1113
  },
1244
1114
  callback);
1245
- };
1115
+ }
1246
1116
  if (arguments.length > 2) {
1247
1117
  var args = _baseSlice(arguments, 2);
1248
1118
  return go.apply(this, args);
@@ -1250,23 +1120,52 @@
1250
1120
  else {
1251
1121
  return go;
1252
1122
  }
1123
+ }
1124
+
1125
+ async.applyEach = function (/*fns, args...*/) {
1126
+ var args = _baseSlice(arguments);
1127
+ return _applyEach.apply(null, [async.eachOf].concat(args));
1128
+ };
1129
+ async.applyEachSeries = function (/*fns, args...*/) {
1130
+ var args = _baseSlice(arguments);
1131
+ return _applyEach.apply(null, [async.eachOfSeries].concat(args));
1253
1132
  };
1254
- async.applyEach = doParallel(_applyEach);
1255
- async.applyEachSeries = doSeries(_applyEach);
1133
+
1256
1134
 
1257
1135
  async.forever = function (fn, callback) {
1136
+ var done = only_once(callback || noop);
1137
+ var task = ensureAsync(fn);
1258
1138
  function next(err) {
1259
1139
  if (err) {
1260
- if (callback) {
1261
- return callback(err);
1262
- }
1263
- throw err;
1140
+ return done(err);
1264
1141
  }
1265
- fn(next);
1142
+ task(next);
1266
1143
  }
1267
1144
  next();
1268
1145
  };
1269
1146
 
1147
+ function ensureAsync(fn) {
1148
+ return function (/*...args, callback*/) {
1149
+ var args = _baseSlice(arguments);
1150
+ var callback = args.pop();
1151
+ args.push(function () {
1152
+ var innerArgs = arguments;
1153
+ if (sync) {
1154
+ async.setImmediate(function () {
1155
+ callback.apply(null, innerArgs);
1156
+ });
1157
+ } else {
1158
+ callback.apply(null, innerArgs);
1159
+ }
1160
+ });
1161
+ var sync = true;
1162
+ fn.apply(this, args);
1163
+ sync = false;
1164
+ };
1165
+ }
1166
+
1167
+ async.ensureAsync = ensureAsync;
1168
+
1270
1169
  // Node.js
1271
1170
  if (typeof module !== 'undefined' && module.exports) {
1272
1171
  module.exports = async;