async.js 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958
  1. /*global setImmediate: false, setTimeout: false, console: false */
  2. (function () {
  3. var async = {};
  4. // global on the server, window in the browser
  5. var root, previous_async;
  6. root = this;
  7. if (root != null) {
  8. previous_async = root.async;
  9. }
  10. async.noConflict = function () {
  11. root.async = previous_async;
  12. return async;
  13. };
  14. function only_once(fn) {
  15. var called = false;
  16. return function() {
  17. if (called) throw new Error("Callback was already called.");
  18. called = true;
  19. fn.apply(root, arguments);
  20. }
  21. }
  22. //// cross-browser compatiblity functions ////
  23. var _each = function (arr, iterator) {
  24. if (arr.forEach) {
  25. return arr.forEach(iterator);
  26. }
  27. for (var i = 0; i < arr.length; i += 1) {
  28. iterator(arr[i], i, arr);
  29. }
  30. };
  31. var _map = function (arr, iterator) {
  32. if (arr.map) {
  33. return arr.map(iterator);
  34. }
  35. var results = [];
  36. _each(arr, function (x, i, a) {
  37. results.push(iterator(x, i, a));
  38. });
  39. return results;
  40. };
  41. var _reduce = function (arr, iterator, memo) {
  42. if (arr.reduce) {
  43. return arr.reduce(iterator, memo);
  44. }
  45. _each(arr, function (x, i, a) {
  46. memo = iterator(memo, x, i, a);
  47. });
  48. return memo;
  49. };
  50. var _keys = function (obj) {
  51. if (Object.keys) {
  52. return Object.keys(obj);
  53. }
  54. var keys = [];
  55. for (var k in obj) {
  56. if (obj.hasOwnProperty(k)) {
  57. keys.push(k);
  58. }
  59. }
  60. return keys;
  61. };
  62. //// exported async module functions ////
  63. //// nextTick implementation with browser-compatible fallback ////
  64. if (typeof process === 'undefined' || !(process.nextTick)) {
  65. if (typeof setImmediate === 'function') {
  66. async.nextTick = function (fn) {
  67. // not a direct alias for IE10 compatibility
  68. setImmediate(fn);
  69. };
  70. async.setImmediate = async.nextTick;
  71. }
  72. else {
  73. async.nextTick = function (fn) {
  74. setTimeout(fn, 0);
  75. };
  76. async.setImmediate = async.nextTick;
  77. }
  78. }
  79. else {
  80. async.nextTick = process.nextTick;
  81. if (typeof setImmediate !== 'undefined') {
  82. async.setImmediate = function (fn) {
  83. // not a direct alias for IE10 compatibility
  84. setImmediate(fn);
  85. };
  86. }
  87. else {
  88. async.setImmediate = async.nextTick;
  89. }
  90. }
  91. async.each = function (arr, iterator, callback) {
  92. callback = callback || function () {};
  93. if (!arr.length) {
  94. return callback();
  95. }
  96. var completed = 0;
  97. _each(arr, function (x) {
  98. iterator(x, only_once(function (err) {
  99. if (err) {
  100. callback(err);
  101. callback = function () {};
  102. }
  103. else {
  104. completed += 1;
  105. if (completed >= arr.length) {
  106. callback(null);
  107. }
  108. }
  109. }));
  110. });
  111. };
  112. async.forEach = async.each;
  113. async.eachSeries = function (arr, iterator, callback) {
  114. callback = callback || function () {};
  115. if (!arr.length) {
  116. return callback();
  117. }
  118. var completed = 0;
  119. var iterate = function () {
  120. iterator(arr[completed], function (err) {
  121. if (err) {
  122. callback(err);
  123. callback = function () {};
  124. }
  125. else {
  126. completed += 1;
  127. if (completed >= arr.length) {
  128. callback(null);
  129. }
  130. else {
  131. iterate();
  132. }
  133. }
  134. });
  135. };
  136. iterate();
  137. };
  138. async.forEachSeries = async.eachSeries;
  139. async.eachLimit = function (arr, limit, iterator, callback) {
  140. var fn = _eachLimit(limit);
  141. fn.apply(null, [arr, iterator, callback]);
  142. };
  143. async.forEachLimit = async.eachLimit;
  144. var _eachLimit = function (limit) {
  145. return function (arr, iterator, callback) {
  146. callback = callback || function () {};
  147. if (!arr.length || limit <= 0) {
  148. return callback();
  149. }
  150. var completed = 0;
  151. var started = 0;
  152. var running = 0;
  153. (function replenish () {
  154. if (completed >= arr.length) {
  155. return callback();
  156. }
  157. while (running < limit && started < arr.length) {
  158. started += 1;
  159. running += 1;
  160. iterator(arr[started - 1], function (err) {
  161. if (err) {
  162. callback(err);
  163. callback = function () {};
  164. }
  165. else {
  166. completed += 1;
  167. running -= 1;
  168. if (completed >= arr.length) {
  169. callback();
  170. }
  171. else {
  172. replenish();
  173. }
  174. }
  175. });
  176. }
  177. })();
  178. };
  179. };
  180. var doParallel = function (fn) {
  181. return function () {
  182. var args = Array.prototype.slice.call(arguments);
  183. return fn.apply(null, [async.each].concat(args));
  184. };
  185. };
  186. var doParallelLimit = function(limit, fn) {
  187. return function () {
  188. var args = Array.prototype.slice.call(arguments);
  189. return fn.apply(null, [_eachLimit(limit)].concat(args));
  190. };
  191. };
  192. var doSeries = function (fn) {
  193. return function () {
  194. var args = Array.prototype.slice.call(arguments);
  195. return fn.apply(null, [async.eachSeries].concat(args));
  196. };
  197. };
  198. var _asyncMap = function (eachfn, arr, iterator, callback) {
  199. var results = [];
  200. arr = _map(arr, function (x, i) {
  201. return {index: i, value: x};
  202. });
  203. eachfn(arr, function (x, callback) {
  204. iterator(x.value, function (err, v) {
  205. results[x.index] = v;
  206. callback(err);
  207. });
  208. }, function (err) {
  209. callback(err, results);
  210. });
  211. };
  212. async.map = doParallel(_asyncMap);
  213. async.mapSeries = doSeries(_asyncMap);
  214. async.mapLimit = function (arr, limit, iterator, callback) {
  215. return _mapLimit(limit)(arr, iterator, callback);
  216. };
  217. var _mapLimit = function(limit) {
  218. return doParallelLimit(limit, _asyncMap);
  219. };
  220. // reduce only has a series version, as doing reduce in parallel won't
  221. // work in many situations.
  222. async.reduce = function (arr, memo, iterator, callback) {
  223. async.eachSeries(arr, function (x, callback) {
  224. iterator(memo, x, function (err, v) {
  225. memo = v;
  226. callback(err);
  227. });
  228. }, function (err) {
  229. callback(err, memo);
  230. });
  231. };
  232. // inject alias
  233. async.inject = async.reduce;
  234. // foldl alias
  235. async.foldl = async.reduce;
  236. async.reduceRight = function (arr, memo, iterator, callback) {
  237. var reversed = _map(arr, function (x) {
  238. return x;
  239. }).reverse();
  240. async.reduce(reversed, memo, iterator, callback);
  241. };
  242. // foldr alias
  243. async.foldr = async.reduceRight;
  244. var _filter = function (eachfn, arr, iterator, callback) {
  245. var results = [];
  246. arr = _map(arr, function (x, i) {
  247. return {index: i, value: x};
  248. });
  249. eachfn(arr, function (x, callback) {
  250. iterator(x.value, function (v) {
  251. if (v) {
  252. results.push(x);
  253. }
  254. callback();
  255. });
  256. }, function (err) {
  257. callback(_map(results.sort(function (a, b) {
  258. return a.index - b.index;
  259. }), function (x) {
  260. return x.value;
  261. }));
  262. });
  263. };
  264. async.filter = doParallel(_filter);
  265. async.filterSeries = doSeries(_filter);
  266. // select alias
  267. async.select = async.filter;
  268. async.selectSeries = async.filterSeries;
  269. var _reject = function (eachfn, arr, iterator, callback) {
  270. var results = [];
  271. arr = _map(arr, function (x, i) {
  272. return {index: i, value: x};
  273. });
  274. eachfn(arr, function (x, callback) {
  275. iterator(x.value, function (v) {
  276. if (!v) {
  277. results.push(x);
  278. }
  279. callback();
  280. });
  281. }, function (err) {
  282. callback(_map(results.sort(function (a, b) {
  283. return a.index - b.index;
  284. }), function (x) {
  285. return x.value;
  286. }));
  287. });
  288. };
  289. async.reject = doParallel(_reject);
  290. async.rejectSeries = doSeries(_reject);
  291. var _detect = function (eachfn, arr, iterator, main_callback) {
  292. eachfn(arr, function (x, callback) {
  293. iterator(x, function (result) {
  294. if (result) {
  295. main_callback(x);
  296. main_callback = function () {};
  297. }
  298. else {
  299. callback();
  300. }
  301. });
  302. }, function (err) {
  303. main_callback();
  304. });
  305. };
  306. async.detect = doParallel(_detect);
  307. async.detectSeries = doSeries(_detect);
  308. async.some = function (arr, iterator, main_callback) {
  309. async.each(arr, function (x, callback) {
  310. iterator(x, function (v) {
  311. if (v) {
  312. main_callback(true);
  313. main_callback = function () {};
  314. }
  315. callback();
  316. });
  317. }, function (err) {
  318. main_callback(false);
  319. });
  320. };
  321. // any alias
  322. async.any = async.some;
  323. async.every = function (arr, iterator, main_callback) {
  324. async.each(arr, function (x, callback) {
  325. iterator(x, function (v) {
  326. if (!v) {
  327. main_callback(false);
  328. main_callback = function () {};
  329. }
  330. callback();
  331. });
  332. }, function (err) {
  333. main_callback(true);
  334. });
  335. };
  336. // all alias
  337. async.all = async.every;
  338. async.sortBy = function (arr, iterator, callback) {
  339. async.map(arr, function (x, callback) {
  340. iterator(x, function (err, criteria) {
  341. if (err) {
  342. callback(err);
  343. }
  344. else {
  345. callback(null, {value: x, criteria: criteria});
  346. }
  347. });
  348. }, function (err, results) {
  349. if (err) {
  350. return callback(err);
  351. }
  352. else {
  353. var fn = function (left, right) {
  354. var a = left.criteria, b = right.criteria;
  355. return a < b ? -1 : a > b ? 1 : 0;
  356. };
  357. callback(null, _map(results.sort(fn), function (x) {
  358. return x.value;
  359. }));
  360. }
  361. });
  362. };
  363. async.auto = function (tasks, callback) {
  364. callback = callback || function () {};
  365. var keys = _keys(tasks);
  366. if (!keys.length) {
  367. return callback(null);
  368. }
  369. var results = {};
  370. var listeners = [];
  371. var addListener = function (fn) {
  372. listeners.unshift(fn);
  373. };
  374. var removeListener = function (fn) {
  375. for (var i = 0; i < listeners.length; i += 1) {
  376. if (listeners[i] === fn) {
  377. listeners.splice(i, 1);
  378. return;
  379. }
  380. }
  381. };
  382. var taskComplete = function () {
  383. _each(listeners.slice(0), function (fn) {
  384. fn();
  385. });
  386. };
  387. addListener(function () {
  388. if (_keys(results).length === keys.length) {
  389. callback(null, results);
  390. callback = function () {};
  391. }
  392. });
  393. _each(keys, function (k) {
  394. var task = (tasks[k] instanceof Function) ? [tasks[k]]: tasks[k];
  395. var taskCallback = function (err) {
  396. var args = Array.prototype.slice.call(arguments, 1);
  397. if (args.length <= 1) {
  398. args = args[0];
  399. }
  400. if (err) {
  401. var safeResults = {};
  402. _each(_keys(results), function(rkey) {
  403. safeResults[rkey] = results[rkey];
  404. });
  405. safeResults[k] = args;
  406. callback(err, safeResults);
  407. // stop subsequent errors hitting callback multiple times
  408. callback = function () {};
  409. }
  410. else {
  411. results[k] = args;
  412. async.setImmediate(taskComplete);
  413. }
  414. };
  415. var requires = task.slice(0, Math.abs(task.length - 1)) || [];
  416. var ready = function () {
  417. return _reduce(requires, function (a, x) {
  418. return (a && results.hasOwnProperty(x));
  419. }, true) && !results.hasOwnProperty(k);
  420. };
  421. if (ready()) {
  422. task[task.length - 1](taskCallback, results);
  423. }
  424. else {
  425. var listener = function () {
  426. if (ready()) {
  427. removeListener(listener);
  428. task[task.length - 1](taskCallback, results);
  429. }
  430. };
  431. addListener(listener);
  432. }
  433. });
  434. };
  435. async.waterfall = function (tasks, callback) {
  436. callback = callback || function () {};
  437. if (tasks.constructor !== Array) {
  438. var err = new Error('First argument to waterfall must be an array of functions');
  439. return callback(err);
  440. }
  441. if (!tasks.length) {
  442. return callback();
  443. }
  444. var wrapIterator = function (iterator) {
  445. return function (err) {
  446. if (err) {
  447. callback.apply(null, arguments);
  448. callback = function () {};
  449. }
  450. else {
  451. var args = Array.prototype.slice.call(arguments, 1);
  452. var next = iterator.next();
  453. if (next) {
  454. args.push(wrapIterator(next));
  455. }
  456. else {
  457. args.push(callback);
  458. }
  459. async.setImmediate(function () {
  460. iterator.apply(null, args);
  461. });
  462. }
  463. };
  464. };
  465. wrapIterator(async.iterator(tasks))();
  466. };
  467. var _parallel = function(eachfn, tasks, callback) {
  468. callback = callback || function () {};
  469. if (tasks.constructor === Array) {
  470. eachfn.map(tasks, function (fn, callback) {
  471. if (fn) {
  472. fn(function (err) {
  473. var args = Array.prototype.slice.call(arguments, 1);
  474. if (args.length <= 1) {
  475. args = args[0];
  476. }
  477. callback.call(null, err, args);
  478. });
  479. }
  480. }, callback);
  481. }
  482. else {
  483. var results = {};
  484. eachfn.each(_keys(tasks), function (k, callback) {
  485. tasks[k](function (err) {
  486. var args = Array.prototype.slice.call(arguments, 1);
  487. if (args.length <= 1) {
  488. args = args[0];
  489. }
  490. results[k] = args;
  491. callback(err);
  492. });
  493. }, function (err) {
  494. callback(err, results);
  495. });
  496. }
  497. };
  498. async.parallel = function (tasks, callback) {
  499. _parallel({ map: async.map, each: async.each }, tasks, callback);
  500. };
  501. async.parallelLimit = function(tasks, limit, callback) {
  502. _parallel({ map: _mapLimit(limit), each: _eachLimit(limit) }, tasks, callback);
  503. };
  504. async.series = function (tasks, callback) {
  505. callback = callback || function () {};
  506. if (tasks.constructor === Array) {
  507. async.mapSeries(tasks, function (fn, callback) {
  508. if (fn) {
  509. fn(function (err) {
  510. var args = Array.prototype.slice.call(arguments, 1);
  511. if (args.length <= 1) {
  512. args = args[0];
  513. }
  514. callback.call(null, err, args);
  515. });
  516. }
  517. }, callback);
  518. }
  519. else {
  520. var results = {};
  521. async.eachSeries(_keys(tasks), function (k, callback) {
  522. tasks[k](function (err) {
  523. var args = Array.prototype.slice.call(arguments, 1);
  524. if (args.length <= 1) {
  525. args = args[0];
  526. }
  527. results[k] = args;
  528. callback(err);
  529. });
  530. }, function (err) {
  531. callback(err, results);
  532. });
  533. }
  534. };
  535. async.iterator = function (tasks) {
  536. var makeCallback = function (index) {
  537. var fn = function () {
  538. if (tasks.length) {
  539. tasks[index].apply(null, arguments);
  540. }
  541. return fn.next();
  542. };
  543. fn.next = function () {
  544. return (index < tasks.length - 1) ? makeCallback(index + 1): null;
  545. };
  546. return fn;
  547. };
  548. return makeCallback(0);
  549. };
  550. async.apply = function (fn) {
  551. var args = Array.prototype.slice.call(arguments, 1);
  552. return function () {
  553. return fn.apply(
  554. null, args.concat(Array.prototype.slice.call(arguments))
  555. );
  556. };
  557. };
  558. var _concat = function (eachfn, arr, fn, callback) {
  559. var r = [];
  560. eachfn(arr, function (x, cb) {
  561. fn(x, function (err, y) {
  562. r = r.concat(y || []);
  563. cb(err);
  564. });
  565. }, function (err) {
  566. callback(err, r);
  567. });
  568. };
  569. async.concat = doParallel(_concat);
  570. async.concatSeries = doSeries(_concat);
  571. async.whilst = function (test, iterator, callback) {
  572. if (test()) {
  573. iterator(function (err) {
  574. if (err) {
  575. return callback(err);
  576. }
  577. async.whilst(test, iterator, callback);
  578. });
  579. }
  580. else {
  581. callback();
  582. }
  583. };
  584. async.doWhilst = function (iterator, test, callback) {
  585. iterator(function (err) {
  586. if (err) {
  587. return callback(err);
  588. }
  589. if (test()) {
  590. async.doWhilst(iterator, test, callback);
  591. }
  592. else {
  593. callback();
  594. }
  595. });
  596. };
  597. async.until = function (test, iterator, callback) {
  598. if (!test()) {
  599. iterator(function (err) {
  600. if (err) {
  601. return callback(err);
  602. }
  603. async.until(test, iterator, callback);
  604. });
  605. }
  606. else {
  607. callback();
  608. }
  609. };
  610. async.doUntil = function (iterator, test, callback) {
  611. iterator(function (err) {
  612. if (err) {
  613. return callback(err);
  614. }
  615. if (!test()) {
  616. async.doUntil(iterator, test, callback);
  617. }
  618. else {
  619. callback();
  620. }
  621. });
  622. };
  623. async.queue = function (worker, concurrency) {
  624. if (concurrency === undefined) {
  625. concurrency = 1;
  626. }
  627. function _insert(q, data, pos, callback) {
  628. if(data.constructor !== Array) {
  629. data = [data];
  630. }
  631. _each(data, function(task) {
  632. var item = {
  633. data: task,
  634. callback: typeof callback === 'function' ? callback : null
  635. };
  636. if (pos) {
  637. q.tasks.unshift(item);
  638. } else {
  639. q.tasks.push(item);
  640. }
  641. if (q.saturated && q.tasks.length === concurrency) {
  642. q.saturated();
  643. }
  644. async.setImmediate(q.process);
  645. });
  646. }
  647. var workers = 0;
  648. var q = {
  649. tasks: [],
  650. concurrency: concurrency,
  651. saturated: null,
  652. empty: null,
  653. drain: null,
  654. push: function (data, callback) {
  655. _insert(q, data, false, callback);
  656. },
  657. unshift: function (data, callback) {
  658. _insert(q, data, true, callback);
  659. },
  660. process: function () {
  661. if (workers < q.concurrency && q.tasks.length) {
  662. var task = q.tasks.shift();
  663. if (q.empty && q.tasks.length === 0) {
  664. q.empty();
  665. }
  666. workers += 1;
  667. var next = function () {
  668. workers -= 1;
  669. if (task.callback) {
  670. task.callback.apply(task, arguments);
  671. }
  672. if (q.drain && q.tasks.length + workers === 0) {
  673. q.drain();
  674. }
  675. q.process();
  676. };
  677. var cb = only_once(next);
  678. worker(task.data, cb);
  679. }
  680. },
  681. length: function () {
  682. return q.tasks.length;
  683. },
  684. running: function () {
  685. return workers;
  686. }
  687. };
  688. return q;
  689. };
  690. async.cargo = function (worker, payload) {
  691. var working = false,
  692. tasks = [];
  693. var cargo = {
  694. tasks: tasks,
  695. payload: payload,
  696. saturated: null,
  697. empty: null,
  698. drain: null,
  699. push: function (data, callback) {
  700. if(data.constructor !== Array) {
  701. data = [data];
  702. }
  703. _each(data, function(task) {
  704. tasks.push({
  705. data: task,
  706. callback: typeof callback === 'function' ? callback : null
  707. });
  708. if (cargo.saturated && tasks.length === payload) {
  709. cargo.saturated();
  710. }
  711. });
  712. async.setImmediate(cargo.process);
  713. },
  714. process: function process() {
  715. if (working) return;
  716. if (tasks.length === 0) {
  717. if(cargo.drain) cargo.drain();
  718. return;
  719. }
  720. var ts = typeof payload === 'number'
  721. ? tasks.splice(0, payload)
  722. : tasks.splice(0);
  723. var ds = _map(ts, function (task) {
  724. return task.data;
  725. });
  726. if(cargo.empty) cargo.empty();
  727. working = true;
  728. worker(ds, function () {
  729. working = false;
  730. var args = arguments;
  731. _each(ts, function (data) {
  732. if (data.callback) {
  733. data.callback.apply(null, args);
  734. }
  735. });
  736. process();
  737. });
  738. },
  739. length: function () {
  740. return tasks.length;
  741. },
  742. running: function () {
  743. return working;
  744. }
  745. };
  746. return cargo;
  747. };
  748. var _console_fn = function (name) {
  749. return function (fn) {
  750. var args = Array.prototype.slice.call(arguments, 1);
  751. fn.apply(null, args.concat([function (err) {
  752. var args = Array.prototype.slice.call(arguments, 1);
  753. if (typeof console !== 'undefined') {
  754. if (err) {
  755. if (console.error) {
  756. console.error(err);
  757. }
  758. }
  759. else if (console[name]) {
  760. _each(args, function (x) {
  761. console[name](x);
  762. });
  763. }
  764. }
  765. }]));
  766. };
  767. };
  768. async.log = _console_fn('log');
  769. async.dir = _console_fn('dir');
  770. /*async.info = _console_fn('info');
  771. async.warn = _console_fn('warn');
  772. async.error = _console_fn('error');*/
  773. async.memoize = function (fn, hasher) {
  774. var memo = {};
  775. var queues = {};
  776. hasher = hasher || function (x) {
  777. return x;
  778. };
  779. var memoized = function () {
  780. var args = Array.prototype.slice.call(arguments);
  781. var callback = args.pop();
  782. var key = hasher.apply(null, args);
  783. if (key in memo) {
  784. callback.apply(null, memo[key]);
  785. }
  786. else if (key in queues) {
  787. queues[key].push(callback);
  788. }
  789. else {
  790. queues[key] = [callback];
  791. fn.apply(null, args.concat([function () {
  792. memo[key] = arguments;
  793. var q = queues[key];
  794. delete queues[key];
  795. for (var i = 0, l = q.length; i < l; i++) {
  796. q[i].apply(null, arguments);
  797. }
  798. }]));
  799. }
  800. };
  801. memoized.memo = memo;
  802. memoized.unmemoized = fn;
  803. return memoized;
  804. };
  805. async.unmemoize = function (fn) {
  806. return function () {
  807. return (fn.unmemoized || fn).apply(null, arguments);
  808. };
  809. };
  810. async.times = function (count, iterator, callback) {
  811. var counter = [];
  812. for (var i = 0; i < count; i++) {
  813. counter.push(i);
  814. }
  815. return async.map(counter, iterator, callback);
  816. };
  817. async.timesSeries = function (count, iterator, callback) {
  818. var counter = [];
  819. for (var i = 0; i < count; i++) {
  820. counter.push(i);
  821. }
  822. return async.mapSeries(counter, iterator, callback);
  823. };
  824. async.compose = function (/* functions... */) {
  825. var fns = Array.prototype.reverse.call(arguments);
  826. return function () {
  827. var that = this;
  828. var args = Array.prototype.slice.call(arguments);
  829. var callback = args.pop();
  830. async.reduce(fns, args, function (newargs, fn, cb) {
  831. fn.apply(that, newargs.concat([function () {
  832. var err = arguments[0];
  833. var nextargs = Array.prototype.slice.call(arguments, 1);
  834. cb(err, nextargs);
  835. }]))
  836. },
  837. function (err, results) {
  838. callback.apply(that, [err].concat(results));
  839. });
  840. };
  841. };
  842. var _applyEach = function (eachfn, fns /*args...*/) {
  843. var go = function () {
  844. var that = this;
  845. var args = Array.prototype.slice.call(arguments);
  846. var callback = args.pop();
  847. return eachfn(fns, function (fn, cb) {
  848. fn.apply(that, args.concat([cb]));
  849. },
  850. callback);
  851. };
  852. if (arguments.length > 2) {
  853. var args = Array.prototype.slice.call(arguments, 2);
  854. return go.apply(this, args);
  855. }
  856. else {
  857. return go;
  858. }
  859. };
  860. async.applyEach = doParallel(_applyEach);
  861. async.applyEachSeries = doSeries(_applyEach);
  862. async.forever = function (fn, callback) {
  863. function next(err) {
  864. if (err) {
  865. if (callback) {
  866. return callback(err);
  867. }
  868. throw err;
  869. }
  870. fn(next);
  871. }
  872. next();
  873. };
  874. // AMD / RequireJS
  875. if (typeof define !== 'undefined' && define.amd) {
  876. define([], function () {
  877. return async;
  878. });
  879. }
  880. // Node.js
  881. else if (typeof module !== 'undefined' && module.exports) {
  882. module.exports = async;
  883. }
  884. // included directly via <script> tag
  885. else {
  886. root.async = async;
  887. }
  888. }());