"Fossies" - the Fresh Open Source Software Archive

Member "Atom/resources/app/apm/node_modules/async/lib/async.js" (7 Feb 2017, 29401 Bytes) of archive /windows/misc/atom-windows.zip:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Javascript source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

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