| /*! |
| * async |
| * https://github.com/caolan/async |
| * |
| * Copyright 2010-2014 Caolan McMahon |
| * Released under the MIT license |
| */ |
| (function () { |
| |
| var async = {}; |
| function noop() {} |
| |
| // global on the server, window in the browser |
| var root, previous_async; |
| |
| if (typeof window == 'object' && this === window) { |
| root = window; |
| } |
| else if (typeof global == 'object' && this === global) { |
| root = global; |
| } |
| else { |
| root = this; |
| } |
| |
| if (root != null) { |
| previous_async = root.async; |
| } |
| |
| async.noConflict = function () { |
| root.async = previous_async; |
| return async; |
| }; |
| |
| function only_once(fn) { |
| var called = false; |
| return function() { |
| if (called) throw new Error("Callback was already called."); |
| called = true; |
| fn.apply(this, arguments); |
| }; |
| } |
| |
| function _once(fn) { |
| var called = false; |
| return function() { |
| if (called) return; |
| called = true; |
| fn.apply(this, arguments); |
| }; |
| } |
| |
| //// cross-browser compatiblity functions //// |
| |
| var _toString = Object.prototype.toString; |
| |
| var _isArray = Array.isArray || function (obj) { |
| return _toString.call(obj) === '[object Array]'; |
| }; |
| |
| function _isArrayLike(arr) { |
| return _isArray(arr) || ( |
| // has a positive integer length property |
| typeof arr.length === "number" && |
| arr.length >= 0 && |
| arr.length % 1 === 0 |
| ); |
| } |
| |
| function _each(coll, iterator) { |
| return _isArrayLike(coll) ? |
| _arrayEach(coll, iterator) : |
| _forEachOf(coll, iterator); |
| } |
| |
| function _arrayEach(arr, iterator) { |
| var index = -1, |
| length = arr.length; |
| |
| while (++index < length) { |
| iterator(arr[index], index, arr); |
| } |
| } |
| |
| function _map(arr, iterator) { |
| var index = -1, |
| length = arr.length, |
| result = Array(length); |
| |
| while (++index < length) { |
| result[index] = iterator(arr[index], index, arr); |
| } |
| return result; |
| } |
| |
| function _range(count) { |
| return _map(Array(count), function (v, i) { return i; }); |
| } |
| |
| function _reduce(arr, iterator, memo) { |
| _arrayEach(arr, function (x, i, a) { |
| memo = iterator(memo, x, i, a); |
| }); |
| return memo; |
| } |
| |
| function _forEachOf(object, iterator) { |
| _arrayEach(_keys(object), function (key) { |
| iterator(object[key], key); |
| }); |
| } |
| |
| var _keys = Object.keys || function (obj) { |
| var keys = []; |
| for (var k in obj) { |
| if (obj.hasOwnProperty(k)) { |
| keys.push(k); |
| } |
| } |
| return keys; |
| }; |
| |
| function _keyIterator(coll) { |
| var i = -1; |
| var len; |
| var keys; |
| if (_isArrayLike(coll)) { |
| len = coll.length; |
| return function next() { |
| i++; |
| return i < len ? i : null; |
| }; |
| } else { |
| keys = _keys(coll); |
| len = keys.length; |
| return function next() { |
| i++; |
| return i < len ? keys[i] : null; |
| }; |
| } |
| } |
| |
| function _baseSlice(arr, start) { |
| start = start || 0; |
| var index = -1; |
| var length = arr.length; |
| |
| if (start) { |
| length -= start; |
| length = length < 0 ? 0 : length; |
| } |
| var result = Array(length); |
| |
| while (++index < length) { |
| result[index] = arr[index + start]; |
| } |
| return result; |
| } |
| |
| function _withoutIndex(iterator) { |
| return function (value, index, callback) { |
| return iterator(value, callback); |
| }; |
| } |
| |
| //// exported async module functions //// |
| |
| //// nextTick implementation with browser-compatible fallback //// |
| |
| // capture the global reference to guard against fakeTimer mocks |
| var _setImmediate; |
| if (typeof setImmediate === 'function') { |
| _setImmediate = setImmediate; |
| } |
| |
| if (typeof process === 'undefined' || !(process.nextTick)) { |
| if (_setImmediate) { |
| async.nextTick = function (fn) { |
| // not a direct alias for IE10 compatibility |
| _setImmediate(fn); |
| }; |
| async.setImmediate = async.nextTick; |
| } |
| else { |
| async.nextTick = function (fn) { |
| setTimeout(fn, 0); |
| }; |
| async.setImmediate = async.nextTick; |
| } |
| } |
| else { |
| async.nextTick = process.nextTick; |
| if (_setImmediate) { |
| async.setImmediate = function (fn) { |
| // not a direct alias for IE10 compatibility |
| _setImmediate(fn); |
| }; |
| } |
| else { |
| async.setImmediate = async.nextTick; |
| } |
| } |
| |
| async.forEach = |
| async.each = function (arr, iterator, callback) { |
| return async.eachOf(arr, _withoutIndex(iterator), callback); |
| }; |
| |
| async.forEachSeries = |
| async.eachSeries = function (arr, iterator, callback) { |
| return async.eachOfSeries(arr, _withoutIndex(iterator), callback); |
| }; |
| |
| |
| async.forEachLimit = |
| async.eachLimit = function (arr, limit, iterator, callback) { |
| return _eachOfLimit(limit)(arr, _withoutIndex(iterator), callback); |
| }; |
| |
| async.forEachOf = |
| async.eachOf = function (object, iterator, callback) { |
| callback = _once(callback || noop); |
| object = object || []; |
| var size = _isArrayLike(object) ? object.length : _keys(object).length; |
| var completed = 0; |
| if (!size) { |
| return callback(null); |
| } |
| _each(object, function (value, key) { |
| iterator(object[key], key, only_once(done)); |
| }); |
| function done(err) { |
| if (err) { |
| callback(err); |
| } |
| else { |
| completed += 1; |
| if (completed >= size) { |
| callback(null); |
| } |
| } |
| } |
| }; |
| |
| async.forEachOfSeries = |
| async.eachOfSeries = function (obj, iterator, callback) { |
| callback = _once(callback || noop); |
| obj = obj || []; |
| var nextKey = _keyIterator(obj); |
| var key = nextKey(); |
| function iterate() { |
| var sync = true; |
| if (key === null) { |
| return callback(null); |
| } |
| iterator(obj[key], key, only_once(function (err) { |
| if (err) { |
| callback(err); |
| } |
| else { |
| key = nextKey(); |
| if (key === null) { |
| return callback(null); |
| } else { |
| if (sync) { |
| async.nextTick(iterate); |
| } else { |
| iterate(); |
| } |
| } |
| } |
| })); |
| sync = false; |
| } |
| iterate(); |
| }; |
| |
| |
| |
| async.forEachOfLimit = |
| async.eachOfLimit = function (obj, limit, iterator, callback) { |
| _eachOfLimit(limit)(obj, iterator, callback); |
| }; |
| |
| function _eachOfLimit(limit) { |
| |
| return function (obj, iterator, callback) { |
| callback = _once(callback || noop); |
| obj = obj || []; |
| var nextKey = _keyIterator(obj); |
| if (limit <= 0) { |
| return callback(null); |
| } |
| var done = false; |
| var running = 0; |
| var errored = false; |
| |
| (function replenish () { |
| if (done && running <= 0) { |
| return callback(null); |
| } |
| |
| while (running < limit && !errored) { |
| var key = nextKey(); |
| if (key === null) { |
| done = true; |
| if (running <= 0) { |
| callback(null); |
| } |
| return; |
| } |
| running += 1; |
| iterator(obj[key], key, only_once(function (err) { |
| running -= 1; |
| if (err) { |
| callback(err); |
| errored = true; |
| } |
| else { |
| replenish(); |
| } |
| })); |
| } |
| })(); |
| }; |
| } |
| |
| |
| function doParallel(fn) { |
| return function (obj, iterator, callback) { |
| return fn(async.eachOf, obj, iterator, callback); |
| }; |
| } |
| function doParallelLimit(limit, fn) { |
| return function (obj, iterator, callback) { |
| return fn(_eachOfLimit(limit), obj, iterator, callback); |
| }; |
| } |
| function doSeries(fn) { |
| return function (obj, iterator, callback) { |
| return fn(async.eachOfSeries, obj, iterator, callback); |
| }; |
| } |
| |
| function _asyncMap(eachfn, arr, iterator, callback) { |
| callback = _once(callback || noop); |
| var results = []; |
| eachfn(arr, function (value, index, callback) { |
| iterator(value, function (err, v) { |
| results[index] = v; |
| callback(err); |
| }); |
| }, function (err) { |
| callback(err, results); |
| }); |
| } |
| |
| async.map = doParallel(_asyncMap); |
| async.mapSeries = doSeries(_asyncMap); |
| async.mapLimit = function (arr, limit, iterator, callback) { |
| return _mapLimit(limit)(arr, iterator, callback); |
| }; |
| |
| function _mapLimit(limit) { |
| return doParallelLimit(limit, _asyncMap); |
| } |
| |
| // reduce only has a series version, as doing reduce in parallel won't |
| // work in many situations. |
| async.inject = |
| async.foldl = |
| async.reduce = function (arr, memo, iterator, callback) { |
| async.eachOfSeries(arr, function (x, i, callback) { |
| iterator(memo, x, function (err, v) { |
| memo = v; |
| callback(err); |
| }); |
| }, function (err) { |
| callback(err || null, memo); |
| }); |
| }; |
| |
| async.foldr = |
| async.reduceRight = function (arr, memo, iterator, callback) { |
| var reversed = _map(arr, function (x) { |
| return x; |
| }).reverse(); |
| async.reduce(reversed, memo, iterator, callback); |
| }; |
| |
| function _filter(eachfn, arr, iterator, callback) { |
| var results = []; |
| arr = _map(arr, function (x, i) { |
| return {index: i, value: x}; |
| }); |
| eachfn(arr, function (x, index, callback) { |
| iterator(x.value, function (v) { |
| if (v) { |
| results.push(x); |
| } |
| callback(); |
| }); |
| }, function () { |
| callback(_map(results.sort(function (a, b) { |
| return a.index - b.index; |
| }), function (x) { |
| return x.value; |
| })); |
| }); |
| } |
| |
| async.select = |
| async.filter = doParallel(_filter); |
| |
| async.selectSeries = |
| async.filterSeries = doSeries(_filter); |
| |
| function _reject(eachfn, arr, iterator, callback) { |
| var results = []; |
| arr = _map(arr, function (x, i) { |
| return {index: i, value: x}; |
| }); |
| eachfn(arr, function (x, index, callback) { |
| iterator(x.value, function (v) { |
| if (!v) { |
| results.push(x); |
| } |
| callback(); |
| }); |
| }, function () { |
| callback(_map(results.sort(function (a, b) { |
| return a.index - b.index; |
| }), function (x) { |
| return x.value; |
| })); |
| }); |
| } |
| async.reject = doParallel(_reject); |
| async.rejectSeries = doSeries(_reject); |
| |
| function _detect(eachfn, arr, iterator, main_callback) { |
| eachfn(arr, function (x, index, callback) { |
| iterator(x, function (result) { |
| if (result) { |
| main_callback(x); |
| main_callback = noop; |
| } |
| else { |
| callback(); |
| } |
| }); |
| }, function () { |
| main_callback(); |
| }); |
| } |
| async.detect = doParallel(_detect); |
| async.detectSeries = doSeries(_detect); |
| |
| async.any = |
| async.some = function (arr, iterator, main_callback) { |
| async.eachOf(arr, function (x, _, callback) { |
| iterator(x, function (v) { |
| if (v) { |
| main_callback(true); |
| main_callback = noop; |
| } |
| callback(); |
| }); |
| }, function () { |
| main_callback(false); |
| }); |
| }; |
| |
| async.all = |
| async.every = function (arr, iterator, main_callback) { |
| async.eachOf(arr, function (x, _, callback) { |
| iterator(x, function (v) { |
| if (!v) { |
| main_callback(false); |
| main_callback = noop; |
| } |
| callback(); |
| }); |
| }, function () { |
| main_callback(true); |
| }); |
| }; |
| |
| async.sortBy = function (arr, iterator, callback) { |
| async.map(arr, function (x, callback) { |
| iterator(x, function (err, criteria) { |
| if (err) { |
| callback(err); |
| } |
| else { |
| callback(null, {value: x, criteria: criteria}); |
| } |
| }); |
| }, function (err, results) { |
| if (err) { |
| return callback(err); |
| } |
| else { |
| callback(null, _map(results.sort(comparator), function (x) { |
| return x.value; |
| })); |
| } |
| |
| }); |
| |
| function comparator(left, right) { |
| var a = left.criteria, b = right.criteria; |
| return a < b ? -1 : a > b ? 1 : 0; |
| } |
| }; |
| |
| async.auto = function (tasks, callback) { |
| callback = _once(callback || noop); |
| var keys = _keys(tasks); |
| var remainingTasks = keys.length; |
| if (!remainingTasks) { |
| return callback(null); |
| } |
| |
| var results = {}; |
| |
| var listeners = []; |
| function addListener(fn) { |
| listeners.unshift(fn); |
| } |
| function removeListener(fn) { |
| for (var i = 0; i < listeners.length; i += 1) { |
| if (listeners[i] === fn) { |
| listeners.splice(i, 1); |
| return; |
| } |
| } |
| } |
| function taskComplete() { |
| remainingTasks--; |
| _arrayEach(listeners.slice(0), function (fn) { |
| fn(); |
| }); |
| } |
| |
| addListener(function () { |
| if (!remainingTasks) { |
| callback(null, results); |
| } |
| }); |
| |
| _arrayEach(keys, function (k) { |
| var task = _isArray(tasks[k]) ? tasks[k]: [tasks[k]]; |
| function taskCallback(err) { |
| var args = _baseSlice(arguments, 1); |
| if (args.length <= 1) { |
| args = args[0]; |
| } |
| if (err) { |
| var safeResults = {}; |
| _arrayEach(_keys(results), function(rkey) { |
| safeResults[rkey] = results[rkey]; |
| }); |
| safeResults[k] = args; |
| callback(err, safeResults); |
| } |
| else { |
| results[k] = args; |
| async.setImmediate(taskComplete); |
| } |
| } |
| var requires = task.slice(0, Math.abs(task.length - 1)) || []; |
| // prevent dead-locks |
| var len = requires.length; |
| var dep; |
| while (len--) { |
| if (!(dep = tasks[requires[len]])) { |
| throw new Error('Has inexistant dependency'); |
| } |
| if (_isArray(dep) && !!~dep.indexOf(k)) { |
| throw new Error('Has cyclic dependencies'); |
| } |
| } |
| function ready() { |
| return _reduce(requires, function (a, x) { |
| return (a && results.hasOwnProperty(x)); |
| }, true) && !results.hasOwnProperty(k); |
| } |
| if (ready()) { |
| task[task.length - 1](taskCallback, results); |
| } |
| else { |
| addListener(listener); |
| } |
| function listener() { |
| if (ready()) { |
| removeListener(listener); |
| task[task.length - 1](taskCallback, results); |
| } |
| } |
| }); |
| }; |
| |
| async.retry = function(times, task, callback) { |
| var DEFAULT_TIMES = 5; |
| var attempts = []; |
| // Use defaults if times not passed |
| if (typeof times === 'function') { |
| callback = task; |
| task = times; |
| times = DEFAULT_TIMES; |
| } |
| // Make sure times is a number |
| times = parseInt(times, 10) || DEFAULT_TIMES; |
| |
| function wrappedTask(wrappedCallback, wrappedResults) { |
| function retryAttempt(task, finalAttempt) { |
| return function(seriesCallback) { |
| task(function(err, result){ |
| seriesCallback(!err || finalAttempt, {err: err, result: result}); |
| }, wrappedResults); |
| }; |
| } |
| |
| while (times) { |
| attempts.push(retryAttempt(task, !(times-=1))); |
| } |
| async.series(attempts, function(done, data){ |
| data = data[data.length - 1]; |
| (wrappedCallback || callback)(data.err, data.result); |
| }); |
| } |
| |
| // If a callback is passed, run this as a controll flow |
| return callback ? wrappedTask() : wrappedTask; |
| }; |
| |
| async.waterfall = function (tasks, callback) { |
| callback = _once(callback || noop); |
| if (!_isArray(tasks)) { |
| var err = new Error('First argument to waterfall must be an array of functions'); |
| return callback(err); |
| } |
| if (!tasks.length) { |
| return callback(); |
| } |
| function wrapIterator(iterator) { |
| return function (err) { |
| if (err) { |
| callback.apply(null, arguments); |
| } |
| else { |
| var args = _baseSlice(arguments, 1); |
| var next = iterator.next(); |
| if (next) { |
| args.push(wrapIterator(next)); |
| } |
| else { |
| args.push(callback); |
| } |
| ensureAsync(iterator).apply(null, args); |
| } |
| }; |
| } |
| wrapIterator(async.iterator(tasks))(); |
| }; |
| |
| function _parallel(eachfn, tasks, callback) { |
| callback = callback || noop; |
| var results = _isArrayLike(tasks) ? [] : {}; |
| |
| eachfn(tasks, function (task, key, callback) { |
| task(function (err) { |
| var args = _baseSlice(arguments, 1); |
| if (args.length <= 1) { |
| args = args[0]; |
| } |
| results[key] = args; |
| callback(err); |
| }); |
| }, function (err) { |
| callback(err, results); |
| }); |
| } |
| |
| async.parallel = function (tasks, callback) { |
| _parallel(async.eachOf, tasks, callback); |
| }; |
| |
| async.parallelLimit = function(tasks, limit, callback) { |
| _parallel(_eachOfLimit(limit), tasks, callback); |
| }; |
| |
| async.series = function (tasks, callback) { |
| callback = callback || noop; |
| var results = _isArrayLike(tasks) ? [] : {}; |
| |
| async.eachOfSeries(tasks, function (task, key, callback) { |
| task(function (err) { |
| var args = _baseSlice(arguments, 1); |
| if (args.length <= 1) { |
| args = args[0]; |
| } |
| results[key] = args; |
| callback(err); |
| }); |
| }, function (err) { |
| callback(err, results); |
| }); |
| }; |
| |
| async.iterator = function (tasks) { |
| function makeCallback(index) { |
| function fn() { |
| if (tasks.length) { |
| tasks[index].apply(null, arguments); |
| } |
| return fn.next(); |
| } |
| fn.next = function () { |
| return (index < tasks.length - 1) ? makeCallback(index + 1): null; |
| }; |
| return fn; |
| } |
| return makeCallback(0); |
| }; |
| |
| async.apply = function (fn) { |
| var args = _baseSlice(arguments, 1); |
| return function () { |
| return fn.apply( |
| null, args.concat(_baseSlice(arguments)) |
| ); |
| }; |
| }; |
| |
| function _concat(eachfn, arr, fn, callback) { |
| var result = []; |
| eachfn(arr, function (x, index, cb) { |
| fn(x, function (err, y) { |
| result = result.concat(y || []); |
| cb(err); |
| }); |
| }, function (err) { |
| callback(err, result); |
| }); |
| } |
| async.concat = doParallel(_concat); |
| async.concatSeries = doSeries(_concat); |
| |
| async.whilst = function (test, iterator, callback) { |
| if (test()) { |
| iterator(function (err) { |
| if (err) { |
| return callback(err); |
| } |
| async.whilst(test, iterator, callback); |
| }); |
| } |
| else { |
| callback(null); |
| } |
| }; |
| |
| async.doWhilst = function (iterator, test, callback) { |
| iterator(function (err) { |
| if (err) { |
| return callback(err); |
| } |
| var args = _baseSlice(arguments, 1); |
| if (test.apply(null, args)) { |
| async.doWhilst(iterator, test, callback); |
| } |
| else { |
| callback(null); |
| } |
| }); |
| }; |
| |
| async.until = function (test, iterator, callback) { |
| if (!test()) { |
| iterator(function (err) { |
| if (err) { |
| return callback(err); |
| } |
| async.until(test, iterator, callback); |
| }); |
| } |
| else { |
| callback(null); |
| } |
| }; |
| |
| async.doUntil = function (iterator, test, callback) { |
| iterator(function (err) { |
| if (err) { |
| return callback(err); |
| } |
| var args = _baseSlice(arguments, 1); |
| if (!test.apply(null, args)) { |
| async.doUntil(iterator, test, callback); |
| } |
| else { |
| callback(null); |
| } |
| }); |
| }; |
| |
| function _queue(worker, concurrency, payload) { |
| if (concurrency == null) { |
| concurrency = 1; |
| } |
| else if(concurrency === 0) { |
| throw new Error('Concurrency must not be zero'); |
| } |
| function _insert(q, data, pos, callback) { |
| if (callback != null && typeof callback !== "function") { |
| throw new Error("task callback must be a function"); |
| } |
| q.started = true; |
| if (!_isArray(data)) { |
| data = [data]; |
| } |
| if(data.length === 0 && q.idle()) { |
| // call drain immediately if there are no tasks |
| return async.setImmediate(function() { |
| q.drain(); |
| }); |
| } |
| _arrayEach(data, function(task) { |
| var item = { |
| data: task, |
| callback: callback || noop |
| }; |
| |
| if (pos) { |
| q.tasks.unshift(item); |
| } else { |
| q.tasks.push(item); |
| } |
| |
| if (q.tasks.length === q.concurrency) { |
| q.saturated(); |
| } |
| }); |
| async.setImmediate(q.process); |
| } |
| function _next(q, tasks) { |
| return function(){ |
| workers -= 1; |
| var args = arguments; |
| _arrayEach(tasks, function (task) { |
| task.callback.apply(task, args); |
| }); |
| if (q.tasks.length + workers === 0) { |
| q.drain(); |
| } |
| q.process(); |
| }; |
| } |
| |
| var workers = 0; |
| var q = { |
| tasks: [], |
| concurrency: concurrency, |
| saturated: noop, |
| empty: noop, |
| drain: noop, |
| started: false, |
| paused: false, |
| push: function (data, callback) { |
| _insert(q, data, false, callback); |
| }, |
| kill: function () { |
| q.drain = noop; |
| q.tasks = []; |
| }, |
| unshift: function (data, callback) { |
| _insert(q, data, true, callback); |
| }, |
| process: function () { |
| if (!q.paused && workers < q.concurrency && q.tasks.length) { |
| while(workers < q.concurrency && q.tasks.length){ |
| var tasks = payload ? |
| q.tasks.splice(0, payload) : |
| q.tasks.splice(0, q.tasks.length); |
| |
| var data = _map(tasks, function (task) { |
| return task.data; |
| }); |
| |
| if (q.tasks.length === 0) { |
| q.empty(); |
| } |
| workers += 1; |
| var cb = only_once(_next(q, tasks)); |
| worker(data, cb); |
| } |
| } |
| }, |
| length: function () { |
| return q.tasks.length; |
| }, |
| running: function () { |
| return workers; |
| }, |
| idle: function() { |
| return q.tasks.length + workers === 0; |
| }, |
| pause: function () { |
| q.paused = true; |
| }, |
| resume: function () { |
| if (q.paused === false) { return; } |
| q.paused = false; |
| var resumeCount = Math.min(q.concurrency, q.tasks.length); |
| // Need to call q.process once per concurrent |
| // worker to preserve full concurrency after pause |
| for (var w = 1; w <= resumeCount; w++) { |
| async.setImmediate(q.process); |
| } |
| } |
| }; |
| return q; |
| } |
| |
| async.queue = function (worker, concurrency) { |
| var q = _queue(function (items, cb) { |
| worker(items[0], cb); |
| }, concurrency, 1); |
| |
| return q; |
| }; |
| |
| async.priorityQueue = function (worker, concurrency) { |
| |
| function _compareTasks(a, b){ |
| return a.priority - b.priority; |
| } |
| |
| function _binarySearch(sequence, item, compare) { |
| var beg = -1, |
| end = sequence.length - 1; |
| while (beg < end) { |
| var mid = beg + ((end - beg + 1) >>> 1); |
| if (compare(item, sequence[mid]) >= 0) { |
| beg = mid; |
| } else { |
| end = mid - 1; |
| } |
| } |
| return beg; |
| } |
| |
| function _insert(q, data, priority, callback) { |
| if (callback != null && typeof callback !== "function") { |
| throw new Error("task callback must be a function"); |
| } |
| q.started = true; |
| if (!_isArray(data)) { |
| data = [data]; |
| } |
| if(data.length === 0) { |
| // call drain immediately if there are no tasks |
| return async.setImmediate(function() { |
| q.drain(); |
| }); |
| } |
| _arrayEach(data, function(task) { |
| var item = { |
| data: task, |
| priority: priority, |
| callback: typeof callback === 'function' ? callback : noop |
| }; |
| |
| q.tasks.splice(_binarySearch(q.tasks, item, _compareTasks) + 1, 0, item); |
| |
| if (q.tasks.length === q.concurrency) { |
| q.saturated(); |
| } |
| async.setImmediate(q.process); |
| }); |
| } |
| |
| // Start with a normal queue |
| var q = async.queue(worker, concurrency); |
| |
| // Override push to accept second parameter representing priority |
| q.push = function (data, priority, callback) { |
| _insert(q, data, priority, callback); |
| }; |
| |
| // Remove unshift function |
| delete q.unshift; |
| |
| return q; |
| }; |
| |
| async.cargo = function (worker, payload) { |
| return _queue(worker, 1, payload); |
| }; |
| |
| function _console_fn(name) { |
| return function (fn) { |
| var args = _baseSlice(arguments, 1); |
| fn.apply(null, args.concat([function (err) { |
| var args = _baseSlice(arguments, 1); |
| if (typeof console !== 'undefined') { |
| if (err) { |
| if (console.error) { |
| console.error(err); |
| } |
| } |
| else if (console[name]) { |
| _arrayEach(args, function (x) { |
| console[name](x); |
| }); |
| } |
| } |
| }])); |
| }; |
| } |
| async.log = _console_fn('log'); |
| async.dir = _console_fn('dir'); |
| /*async.info = _console_fn('info'); |
| async.warn = _console_fn('warn'); |
| async.error = _console_fn('error');*/ |
| |
| async.memoize = function (fn, hasher) { |
| var memo = {}; |
| var queues = {}; |
| hasher = hasher || function (x) { |
| return x; |
| }; |
| function memoized() { |
| var args = _baseSlice(arguments); |
| var callback = args.pop(); |
| var key = hasher.apply(null, args); |
| if (key in memo) { |
| async.nextTick(function () { |
| callback.apply(null, memo[key]); |
| }); |
| } |
| else if (key in queues) { |
| queues[key].push(callback); |
| } |
| else { |
| queues[key] = [callback]; |
| fn.apply(null, args.concat([function () { |
| memo[key] = _baseSlice(arguments); |
| var q = queues[key]; |
| delete queues[key]; |
| for (var i = 0, l = q.length; i < l; i++) { |
| q[i].apply(null, arguments); |
| } |
| }])); |
| } |
| } |
| memoized.memo = memo; |
| memoized.unmemoized = fn; |
| return memoized; |
| }; |
| |
| async.unmemoize = function (fn) { |
| return function () { |
| return (fn.unmemoized || fn).apply(null, arguments); |
| }; |
| }; |
| |
| function _times(mapper) { |
| return function (count, iterator, callback) { |
| mapper(_range(count), iterator, callback); |
| }; |
| } |
| |
| async.times = _times(async.map); |
| async.timesSeries = _times(async.mapSeries); |
| async.timesLimit = function (count, limit, iterator, callback) { |
| return async.mapLimit(_range(count), limit, iterator, callback); |
| }; |
| |
| async.seq = function (/* functions... */) { |
| var fns = arguments; |
| return function () { |
| var that = this; |
| var args = _baseSlice(arguments); |
| |
| var callback = args.slice(-1)[0]; |
| if (typeof callback == 'function') { |
| args.pop(); |
| } else { |
| callback = noop; |
| } |
| |
| async.reduce(fns, args, function (newargs, fn, cb) { |
| fn.apply(that, newargs.concat([function () { |
| var err = arguments[0]; |
| var nextargs = _baseSlice(arguments, 1); |
| cb(err, nextargs); |
| }])); |
| }, |
| function (err, results) { |
| callback.apply(that, [err].concat(results)); |
| }); |
| }; |
| }; |
| |
| async.compose = function (/* functions... */) { |
| return async.seq.apply(null, Array.prototype.reverse.call(arguments)); |
| }; |
| |
| |
| function _applyEach(eachfn, fns /*args...*/) { |
| function go() { |
| var that = this; |
| var args = _baseSlice(arguments); |
| var callback = args.pop(); |
| return eachfn(fns, function (fn, _, cb) { |
| fn.apply(that, args.concat([cb])); |
| }, |
| callback); |
| } |
| if (arguments.length > 2) { |
| var args = _baseSlice(arguments, 2); |
| return go.apply(this, args); |
| } |
| else { |
| return go; |
| } |
| } |
| |
| async.applyEach = function (/*fns, args...*/) { |
| var args = _baseSlice(arguments); |
| return _applyEach.apply(null, [async.eachOf].concat(args)); |
| }; |
| async.applyEachSeries = function (/*fns, args...*/) { |
| var args = _baseSlice(arguments); |
| return _applyEach.apply(null, [async.eachOfSeries].concat(args)); |
| }; |
| |
| |
| async.forever = function (fn, callback) { |
| var done = only_once(callback || noop); |
| var task = ensureAsync(fn); |
| function next(err) { |
| if (err) { |
| return done(err); |
| } |
| task(next); |
| } |
| next(); |
| }; |
| |
| function ensureAsync(fn) { |
| return function (/*...args, callback*/) { |
| var args = _baseSlice(arguments); |
| var callback = args.pop(); |
| args.push(function () { |
| var innerArgs = arguments; |
| if (sync) { |
| async.setImmediate(function () { |
| callback.apply(null, innerArgs); |
| }); |
| } else { |
| callback.apply(null, innerArgs); |
| } |
| }); |
| var sync = true; |
| fn.apply(this, args); |
| sync = false; |
| }; |
| } |
| |
| async.ensureAsync = ensureAsync; |
| |
| // Node.js |
| if (typeof module !== 'undefined' && module.exports) { |
| module.exports = async; |
| } |
| // AMD / RequireJS |
| else if (typeof define !== 'undefined' && define.amd) { |
| define([], function () { |
| return async; |
| }); |
| } |
| // included directly via <script> tag |
| else { |
| root.async = async; |
| } |
| |
| }()); |