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