PageRenderTime 61ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/files/async/1.4.0/async.js

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