async-rails 1.0.2 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
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;