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