From 465cfe8c919d949e12a1c3215d9eb616cdccc910 Mon Sep 17 00:00:00 2001 From: Farid Neshat Date: Tue, 7 Feb 2017 11:10:29 +0800 Subject: Add async.tryEach, Fixes #687 --- lib/index.js | 3 ++ lib/tryEach.js | 58 ++++++++++++++++++++++++++++++++++ mocha_test/tryEach.js | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 147 insertions(+) create mode 100644 lib/tryEach.js create mode 100644 mocha_test/tryEach.js diff --git a/lib/index.js b/lib/index.js index 8a2c7ca..678b9e6 100644 --- a/lib/index.js +++ b/lib/index.js @@ -89,6 +89,7 @@ import times from './times'; import timesLimit from './timesLimit'; import timesSeries from './timesSeries'; import transform from './transform'; +import tryEach from './tryEach'; import unmemoize from './unmemoize'; import until from './until'; import waterfall from './waterfall'; @@ -163,6 +164,7 @@ export default { timesLimit: timesLimit, timesSeries: timesSeries, transform: transform, + tryEach: tryEach, unmemoize: unmemoize, until: until, waterfall: waterfall, @@ -255,6 +257,7 @@ export { timesLimit as timesLimit, timesSeries as timesSeries, transform as transform, + tryEach as tryEach, unmemoize as unmemoize, until as until, waterfall as waterfall, diff --git a/lib/tryEach.js b/lib/tryEach.js new file mode 100644 index 0000000..d87245f --- /dev/null +++ b/lib/tryEach.js @@ -0,0 +1,58 @@ +import noop from 'lodash/noop'; +import eachSeries from './eachSeries'; +import rest from './internal/rest'; + +/** + * It runs each task in series but stops whenever any of the functions were + * successful. If one of the tasks were successful, the `callback` will be + * passed the result of the successful task. If all tasks fail, the callback + * will be passed the error and result (if any) of the final attempt. + * + * @name tryEach + * @static + * @memberOf module:ControlFlow + * @method + * @category Control Flow + * @param {Array|Iterable|Object} tasks - A collection containing functions to + * run, each function is passed a `callback(err, result)` it must call on + * completion with an error `err` (which can be `null`) and an optional `result` + * value. + * @param {Function} [callback] - An optional callback which is called when one + * of the tasks has succeeded, or all have failed. It receives the `err` and + * `result` arguments of the last attempt at completing the `task`. Invoked with + * (err, results). + * @example + * async.try([ + * function getDataFromFirstWebsite(callback) { + * // Try getting the data from the first website + * callback(err, data); + * }, + * function getDataFromSecondWebsite(callback) { + * // First website failed, + * // Try getting the data from the backup website + * callback(err, data); + * } + * ], + * // optional callback + * function(err, results) { + * Now do something with the data. + * }); + * + */ +export default function tryEach(tasks, callback) { + var error = null; + var result; + callback = callback || noop; + eachSeries(tasks, function(task, callback) { + task(rest(function (err, args) { + if (args.length <= 1) { + args = args[0]; + } + error = err; + result = args; + callback(!err); + })); + }, function () { + callback(error, result); + }); +} diff --git a/mocha_test/tryEach.js b/mocha_test/tryEach.js new file mode 100644 index 0000000..5e997a6 --- /dev/null +++ b/mocha_test/tryEach.js @@ -0,0 +1,86 @@ +var async = require('../lib'); +var expect = require('chai').expect; +var assert = require('assert'); + +describe('try', function () { + it('no callback', function () { + async.tryEach([]); + }); + it('empty', function (done) { + async.tryEach([], function (err, results) { + expect(err).to.equal(null); + expect(results).to.eql(undefined); + done(); + }); + }); + it('one task, multiple results', function (done) { + var RESULTS = ['something', 'something2']; + async.tryEach([ + function (callback) { + callback(null, RESULTS[0], RESULTS[1]); + } + ], function (err, results) { + expect(err).to.equal(null); + expect(results).to.eql(RESULTS); + done(); + }); + }); + it('one task', function (done) { + var RESULT = 'something'; + async.tryEach([ + function (callback) { + callback(null, RESULT); + } + ], function (err, results) { + expect(err).to.equal(null); + expect(results).to.eql(RESULT); + done(); + }); + }); + it('two tasks, one failing', function (done) { + var RESULT = 'something'; + async.tryEach([ + function (callback) { + callback(new Error('Failure'), {}); + }, + function (callback) { + callback(null, RESULT); + } + ], function (err, results) { + expect(err).to.equal(null); + expect(results).to.eql(RESULT); + done(); + }); + }); + it('two tasks, both failing', function (done) { + var ERROR_RESULT = new Error('Failure2'); + async.tryEach([ + function (callback) { + callback(new Error('Should not stop here')); + }, + function (callback) { + callback(ERROR_RESULT); + } + ], function (err, results) { + expect(err).to.equal(ERROR_RESULT); + expect(results).to.eql(undefined); + done(); + }); + }); + it('two tasks, non failing', function (done) { + var RESULT = 'something'; + async.tryEach([ + function (callback) { + callback(null, RESULT); + }, + function () { + assert.fail('Should not been called'); + }, + ], function (err, results) { + expect(err).to.equal(null); + expect(results).to.eql(RESULT); + done(); + }); + }); +}); + -- cgit v1.2.1 From 1af382d62b535f255a699fa03a4043faa5d3514e Mon Sep 17 00:00:00 2001 From: Alexander Early Date: Sun, 2 Apr 2017 23:08:24 -0700 Subject: add list of related libraries to docs intro. Closes #1314 --- intro.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/intro.md b/intro.md index 35e9c76..2185fb3 100644 --- a/intro.md +++ b/intro.md @@ -218,3 +218,10 @@ $ npm install --save async-es import waterfall from 'async-es/waterfall'; import async from 'async-es'; ``` + +## Other Libraries + +* [`limiter`](https://www.npmjs.com/package/limiter) a package for rate-limiting based on requests per sec/hour. +* [`neo-async`](https://www.npmjs.com/package/neo-async) an altername implementation of Async, focusing on speed. +* [`co-async`](https://www.npmjs.com/package/co-async) a library inspired by Async for use with [`co`](https://www.npmjs.com/package/co) and generator functions. +* [`promise-async`](https://www.npmjs.com/package/promise-async) a version of Async where all the methods are Promisified. -- cgit v1.2.1 From cc06eaca633e2b99951b2afdb26ee4d9f12d74f1 Mon Sep 17 00:00:00 2001 From: Alexander Early Date: Sun, 2 Apr 2017 23:48:07 -0700 Subject: add auto benchmark --- perf/suites.js | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/perf/suites.js b/perf/suites.js index ca400dc..677517c 100644 --- a/perf/suites.js +++ b/perf/suites.js @@ -233,6 +233,28 @@ module.exports = [{ fn: function(async, done) { async.waterfall(tasks, done); } +}, { + name: "auto", + args: [ + [5], + [10], + [100] + ], + setup: function setup(count) { + tasks = { + dep1: function (cb) { cb(null, 1); } + }; + _.times(count, function(n) { + var task = ['dep' + (n+1), function(results, cb) { + setImmediate(cb, null, n); + }]; + if (n > 2) task.unshift('dep' + n); + tasks['dep' + (n+2)] = task; + }); + }, + fn: function(async, done) { + async.auto(tasks, done); + } }, { name: "queue", args: [ -- cgit v1.2.1 From 40144660eb1fc75a05102c93d98fe15a16ebd7da Mon Sep 17 00:00:00 2001 From: Alexander Early Date: Sun, 2 Apr 2017 23:49:50 -0700 Subject: optimize auto, parallel, and waterfall by not useing rest() --- lib/auto.js | 14 +++++++------- lib/internal/parallel.js | 12 ++++++------ lib/internal/slice.js | 9 +++++++++ lib/waterfall.js | 10 ++++++---- 4 files changed, 28 insertions(+), 17 deletions(-) create mode 100644 lib/internal/slice.js diff --git a/lib/auto.js b/lib/auto.js index ba0fdc3..d712cc1 100644 --- a/lib/auto.js +++ b/lib/auto.js @@ -4,7 +4,7 @@ import indexOf from 'lodash/_baseIndexOf'; import isArray from 'lodash/isArray'; import okeys from 'lodash/keys'; import noop from 'lodash/noop'; -import rest from './internal/rest'; +import slice from 'lodash/slice'; import once from './internal/once'; import onlyOnce from './internal/onlyOnce'; @@ -192,26 +192,26 @@ export default function (tasks, concurrency, callback) { function runTask(key, task) { if (hasError) return; - var taskCallback = onlyOnce(rest(function(err, args) { + var taskCallback = onlyOnce(function(err, result) { runningTasks--; - if (args.length <= 1) { - args = args[0]; + if (arguments.length > 2) { + result = slice(arguments, 1); } if (err) { var safeResults = {}; forOwn(results, function(val, rkey) { safeResults[rkey] = val; }); - safeResults[key] = args; + safeResults[key] = result; hasError = true; listeners = Object.create(null); callback(err, safeResults); } else { - results[key] = args; + results[key] = result; taskComplete(key); } - })); + }); runningTasks++; var taskFn = wrapAsync(task[task.length - 1]); diff --git a/lib/internal/parallel.js b/lib/internal/parallel.js index 70993d3..f4e9347 100644 --- a/lib/internal/parallel.js +++ b/lib/internal/parallel.js @@ -1,6 +1,6 @@ import noop from 'lodash/noop'; import isArrayLike from 'lodash/isArrayLike'; -import rest from './rest'; +import slice from './slice'; import wrapAsync from './wrapAsync'; export default function _parallel(eachfn, tasks, callback) { @@ -8,13 +8,13 @@ export default function _parallel(eachfn, tasks, callback) { var results = isArrayLike(tasks) ? [] : {}; eachfn(tasks, function (task, key, callback) { - wrapAsync(task)(rest(function (err, args) { - if (args.length <= 1) { - args = args[0]; + wrapAsync(task)(function (err, result) { + if (arguments.length > 2) { + result = slice(arguments, 1); } - results[key] = args; + results[key] = result; callback(err); - })); + }); }, function (err) { callback(err, results); }); diff --git a/lib/internal/slice.js b/lib/internal/slice.js new file mode 100644 index 0000000..cd2e5b3 --- /dev/null +++ b/lib/internal/slice.js @@ -0,0 +1,9 @@ +export default function slice(arrayLike, start) { + start = start|0; + var newLen = Math.max(arrayLike.length - start, 0); + var newArr = Array(newLen); + for(var idx = 0; idx < newLen; idx++) { + newArr[idx] = arrayLike[start + idx]; + } + return newArr; +} diff --git a/lib/waterfall.js b/lib/waterfall.js index 24befac..bfcf7a4 100644 --- a/lib/waterfall.js +++ b/lib/waterfall.js @@ -2,6 +2,7 @@ import isArray from 'lodash/isArray'; import noop from 'lodash/noop'; import once from './internal/once'; import rest from './internal/rest'; +import slice from './internal/slice'; import onlyOnce from './internal/onlyOnce'; import wrapAsync from './internal/wrapAsync'; @@ -74,12 +75,13 @@ export default function(tasks, callback) { return callback.apply(null, [null].concat(args)); } - var taskCallback = onlyOnce(rest(function(err, args) { + var taskCallback = onlyOnce(function(err/*, cbArgs...*/) { + var cbArgs = slice(arguments, 1); if (err) { - return callback.apply(null, [err].concat(args)); + return callback.apply(null, [err].concat(cbArgs)); } - nextTask(args); - })); + nextTask(cbArgs); + }); args.push(taskCallback); -- cgit v1.2.1 From 2857bc74eea2cd888207dfc4e9e23e23a77213bd Mon Sep 17 00:00:00 2001 From: Alexander Early Date: Mon, 3 Apr 2017 00:00:32 -0700 Subject: optimize whilst and family, seq, and reflect --- lib/doDuring.js | 9 +++++---- lib/doWhilst.js | 7 ++++--- lib/reflect.js | 14 +++++--------- lib/seq.js | 6 ++++-- lib/whilst.js | 8 ++++---- 5 files changed, 22 insertions(+), 22 deletions(-) diff --git a/lib/doDuring.js b/lib/doDuring.js index 85a69c2..06aa21e 100644 --- a/lib/doDuring.js +++ b/lib/doDuring.js @@ -1,5 +1,5 @@ import noop from 'lodash/noop'; -import rest from './internal/rest'; +import slice from './internal/slice'; import onlyOnce from './internal/onlyOnce'; import wrapAsync from './internal/wrapAsync'; @@ -28,11 +28,12 @@ export default function doDuring(fn, test, callback) { var _fn = wrapAsync(fn); var _test = wrapAsync(test); - var next = rest(function(err, args) { - if (err) return callback(err); + function next(err/*, args...*/) { + if (err) return callback(err); + var args = slice(arguments, 1); args.push(check); _test.apply(this, args); - }); + }; function check(err, truth) { if (err) return callback(err); diff --git a/lib/doWhilst.js b/lib/doWhilst.js index 4407305..fa07874 100644 --- a/lib/doWhilst.js +++ b/lib/doWhilst.js @@ -1,5 +1,5 @@ import noop from 'lodash/noop'; -import rest from './internal/rest'; +import slice from './internal/slice'; import onlyOnce from './internal/onlyOnce'; import wrapAsync from './internal/wrapAsync'; @@ -29,10 +29,11 @@ import wrapAsync from './internal/wrapAsync'; export default function doWhilst(iteratee, test, callback) { callback = onlyOnce(callback || noop); var _iteratee = wrapAsync(iteratee); - var next = rest(function(err, args) { + var next = function(err/*, args...*/) { if (err) return callback(err); + var args = slice(arguments, 1); if (test.apply(this, args)) return _iteratee(next); callback.apply(null, [null].concat(args)); - }); + }; _iteratee(next); } diff --git a/lib/reflect.js b/lib/reflect.js index 9e0613b..d61c31e 100644 --- a/lib/reflect.js +++ b/lib/reflect.js @@ -1,5 +1,5 @@ import initialParams from './internal/initialParams'; -import rest from './internal/rest'; +import slice from './internal/slice'; import wrapAsync from './internal/wrapAsync'; /** @@ -44,23 +44,19 @@ import wrapAsync from './internal/wrapAsync'; export default function reflect(fn) { var _fn = wrapAsync(fn); return initialParams(function reflectOn(args, reflectCallback) { - args.push(rest(function callback(err, cbArgs) { + args.push(function callback(err, cbArg) { if (err) { reflectCallback(null, { error: err }); } else { - var value = null; - if (cbArgs.length === 1) { - value = cbArgs[0]; - } else if (cbArgs.length > 1) { - value = cbArgs; - } + var value = cbArg; + if (arguments.length > 2) value = slice(arguments, 1); reflectCallback(null, { value: value }); } - })); + }); return _fn.apply(this, args); }); diff --git a/lib/seq.js b/lib/seq.js index 4fceceb..9e86aca 100644 --- a/lib/seq.js +++ b/lib/seq.js @@ -1,5 +1,6 @@ import noop from 'lodash/noop'; import rest from './internal/rest'; +import slice from 'lodash/slice'; import reduce from './reduce'; import wrapAsync from './internal/wrapAsync'; import arrayMap from 'lodash/_arrayMap'; @@ -55,9 +56,10 @@ export default rest(function seq(functions) { } reduce(_functions, args, function(newargs, fn, cb) { - fn.apply(that, newargs.concat(rest(function(err, nextargs) { + fn.apply(that, newargs.concat(function(err/*, nextargs...*/) { + var nextargs = slice(arguments, 1); cb(err, nextargs); - }))); + })); }, function(err, results) { cb.apply(that, [err].concat(results)); diff --git a/lib/whilst.js b/lib/whilst.js index 57edad6..5c8880f 100644 --- a/lib/whilst.js +++ b/lib/whilst.js @@ -1,5 +1,5 @@ import noop from 'lodash/noop'; -import rest from './internal/rest'; +import slice from './internal/slice'; import onlyOnce from './internal/onlyOnce'; import wrapAsync from './internal/wrapAsync'; @@ -42,10 +42,10 @@ export default function whilst(test, iteratee, callback) { callback = onlyOnce(callback || noop); var _iteratee = wrapAsync(iteratee); if (!test()) return callback(null); - var next = rest(function(err, args) { + var next = function(err/*, args...*/) { if (err) return callback(err); if (test()) return _iteratee(next); - callback.apply(null, [null].concat(args)); - }); + callback.apply(null, [null].concat(slice(arguments, 1))); + }; _iteratee(next); } -- cgit v1.2.1 From 2ae34926f070cdeec38f4bcd0ad173fa6a963904 Mon Sep 17 00:00:00 2001 From: Alexander Early Date: Mon, 3 Apr 2017 00:38:41 -0700 Subject: fix lint error --- lib/waterfall.js | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/waterfall.js b/lib/waterfall.js index bfcf7a4..d5245c3 100644 --- a/lib/waterfall.js +++ b/lib/waterfall.js @@ -1,7 +1,6 @@ import isArray from 'lodash/isArray'; import noop from 'lodash/noop'; import once from './internal/once'; -import rest from './internal/rest'; import slice from './internal/slice'; import onlyOnce from './internal/onlyOnce'; -- cgit v1.2.1 From 67e76ea150f30561e9ce7624459031197c45a68a Mon Sep 17 00:00:00 2001 From: Alexander Early Date: Mon, 3 Apr 2017 01:17:11 -0700 Subject: remove rest completely --- lib/apply.js | 15 +++++++++------ lib/compose.js | 8 ++++---- lib/constant.js | 13 +++++++------ lib/internal/applyEach.js | 7 ++++--- lib/internal/consoleFunc.js | 12 +++++++----- lib/internal/initialParams.js | 7 ++++--- lib/internal/queue.js | 11 +++++------ lib/internal/rest.js | 8 -------- lib/internal/setImmediate.js | 7 ++++--- lib/memoize.js | 7 ++++--- lib/reduceRight.js | 5 ++--- lib/seq.js | 14 +++++++------- 12 files changed, 57 insertions(+), 57 deletions(-) delete mode 100644 lib/internal/rest.js diff --git a/lib/apply.js b/lib/apply.js index d3fc18b..b1ca55a 100644 --- a/lib/apply.js +++ b/lib/apply.js @@ -1,4 +1,4 @@ -import rest from './internal/rest'; +import slice from './internal/slice'; /** * Creates a continuation function with some arguments already applied. @@ -12,10 +12,11 @@ import rest from './internal/rest'; * @memberOf module:Utils * @method * @category Util - * @param {Function} function - The function you want to eventually apply all + * @param {Function} fn - The function you want to eventually apply all * arguments to. Invokes with (arguments...). * @param {...*} arguments... - Any number of arguments to automatically apply * when the continuation is called. + * @returns {Function} the partially-applied function * @example * * // using apply @@ -44,8 +45,10 @@ import rest from './internal/rest'; * two * three */ -export default rest(function(fn, args) { - return rest(function(callArgs) { +export default function(fn/*, args*/) { + var args = slice(arguments, 1); + return function(/*callArgs*/) { + var callArgs = slice(arguments); return fn.apply(null, args.concat(callArgs)); - }); -}); + }; +}; diff --git a/lib/compose.js b/lib/compose.js index 96632c0..d9fa760 100644 --- a/lib/compose.js +++ b/lib/compose.js @@ -1,5 +1,5 @@ import seq from './seq'; -import rest from './internal/rest'; +import slice from './internal/slice'; /** * Creates a function which is a composition of the passed asynchronous @@ -36,6 +36,6 @@ import rest from './internal/rest'; * // result now equals 15 * }); */ -export default rest(function(args) { - return seq.apply(null, args.reverse()); -}); +export default function(/*...args*/) { + return seq.apply(null, slice(arguments).reverse()); +}; diff --git a/lib/constant.js b/lib/constant.js index ae6ffd0..238ef61 100644 --- a/lib/constant.js +++ b/lib/constant.js @@ -1,5 +1,4 @@ -import rest from './internal/rest'; -import initialParams from './internal/initialParams'; +import slice from './internal/slice'; /** * Returns a function that when called, calls-back with the values provided. @@ -43,9 +42,11 @@ import initialParams from './internal/initialParams'; * //... * }, callback); */ -export default rest(function(values) { +export default function(/*...values*/) { + var values = slice(arguments); var args = [null].concat(values); - return initialParams(function (ignoredArgs, callback) { + return function (/*...ignoredArgs, callback*/) { + var callback = arguments[arguments.length - 1]; return callback.apply(this, args); - }); -}); + }; +}; diff --git a/lib/internal/applyEach.js b/lib/internal/applyEach.js index 285a6a2..c0ed402 100644 --- a/lib/internal/applyEach.js +++ b/lib/internal/applyEach.js @@ -1,9 +1,10 @@ -import rest from './rest'; +import slice from './slice'; import initialParams from './initialParams'; import wrapAsync from './wrapAsync'; export default function applyEach(eachfn) { - return rest(function(fns, args) { + return function(fns/*, ...args*/) { + var args = slice(arguments, 1); var go = initialParams(function(args, callback) { var that = this; return eachfn(fns, function (fn, cb) { @@ -16,5 +17,5 @@ export default function applyEach(eachfn) { else { return go; } - }); + }; } diff --git a/lib/internal/consoleFunc.js b/lib/internal/consoleFunc.js index 35374d7..92f7e86 100644 --- a/lib/internal/consoleFunc.js +++ b/lib/internal/consoleFunc.js @@ -1,10 +1,12 @@ import arrayEach from 'lodash/_arrayEach'; -import rest from './rest'; +import slice from './slice'; import wrapAsync from './wrapAsync'; export default function consoleFunc(name) { - return rest(function (fn, args) { - wrapAsync(fn).apply(null, args.concat(rest(function (err, args) { + return function (fn/*, ...args*/) { + var args = slice(arguments, 1); + wrapAsync(fn).apply(null, args.concat(function (err/*, ...args*/) { + var args = slice(arguments, 1); if (typeof console === 'object') { if (err) { if (console.error) { @@ -17,6 +19,6 @@ export default function consoleFunc(name) { }); } } - }))); - }); + })); + }; } diff --git a/lib/internal/initialParams.js b/lib/internal/initialParams.js index cf30386..2079703 100644 --- a/lib/internal/initialParams.js +++ b/lib/internal/initialParams.js @@ -1,8 +1,9 @@ -import rest from './rest'; +import slice from './slice'; export default function (fn) { - return rest(function (args/*..., callback*/) { + return function (/*...args, callback*/) { + var args = slice(arguments); var callback = args.pop(); fn.call(this, args, callback); - }); + }; } diff --git a/lib/internal/queue.js b/lib/internal/queue.js index 479eaf8..2eb523a 100644 --- a/lib/internal/queue.js +++ b/lib/internal/queue.js @@ -1,7 +1,6 @@ import indexOf from 'lodash/_baseIndexOf'; import isArray from 'lodash/isArray'; import noop from 'lodash/noop'; -import rest from './rest'; import onlyOnce from './onlyOnce'; import setImmediate from './setImmediate'; @@ -51,7 +50,7 @@ export default function queue(worker, concurrency, payload) { } function _next(tasks) { - return rest(function(args){ + return function(err){ numRunning -= 1; for (var i = 0, l = tasks.length; i < l; i++) { @@ -61,10 +60,10 @@ export default function queue(worker, concurrency, payload) { workersList.splice(index) } - task.callback.apply(task, args); + task.callback.apply(task, arguments); - if (args[0] != null) { - q.error(args[0], task.data); + if (err != null) { + q.error(err, task.data); } } @@ -76,7 +75,7 @@ export default function queue(worker, concurrency, payload) { q.drain(); } q.process(); - }); + }; } var isProcessing = false; diff --git a/lib/internal/rest.js b/lib/internal/rest.js deleted file mode 100644 index ee70cc6..0000000 --- a/lib/internal/rest.js +++ /dev/null @@ -1,8 +0,0 @@ -import _overRest from 'lodash/_overRest'; -import identity from 'lodash/identity'; - -// Lodash rest function without function.toString() -// remappings -export default function rest(func, start) { - return _overRest(func, start, identity); -} diff --git a/lib/internal/setImmediate.js b/lib/internal/setImmediate.js index c8824c7..95191f9 100644 --- a/lib/internal/setImmediate.js +++ b/lib/internal/setImmediate.js @@ -1,6 +1,6 @@ 'use strict'; -import rest from './rest'; +import slice from './slice'; export var hasSetImmediate = typeof setImmediate === 'function' && setImmediate; export var hasNextTick = typeof process === 'object' && typeof process.nextTick === 'function'; @@ -10,11 +10,12 @@ export function fallback(fn) { } export function wrap(defer) { - return rest(function (fn, args) { + return function (fn/*, ...args*/) { + var args = slice(arguments, 1); defer(function () { fn.apply(null, args); }); - }); + }; } var _defer; diff --git a/lib/memoize.js b/lib/memoize.js index de71c33..27c08bc 100644 --- a/lib/memoize.js +++ b/lib/memoize.js @@ -1,5 +1,5 @@ import identity from 'lodash/identity'; -import rest from './internal/rest'; +import slice from './internal/slice'; import setImmediate from './internal/setImmediate'; import initialParams from './internal/initialParams'; @@ -61,14 +61,15 @@ export default function memoize(fn, hasher) { queues[key].push(callback); } else { queues[key] = [callback]; - _fn.apply(null, args.concat(rest(function(args) { + _fn.apply(null, args.concat(function(/*args*/) { + var args = slice(arguments); memo[key] = args; var q = queues[key]; delete queues[key]; for (var i = 0, l = q.length; i < l; i++) { q[i].apply(null, args); } - }))); + })); } }); memoized.memo = memo; diff --git a/lib/reduceRight.js b/lib/reduceRight.js index ca5aa7f..1d203c9 100644 --- a/lib/reduceRight.js +++ b/lib/reduceRight.js @@ -1,6 +1,5 @@ import reduce from './reduce'; - -var slice = Array.prototype.slice; +import slice from './internal/slice'; /** * Same as [`reduce`]{@link module:Collections.reduce}, only operates on `array` in reverse order. @@ -25,6 +24,6 @@ var slice = Array.prototype.slice; * (err, result). */ export default function reduceRight (array, memo, iteratee, callback) { - var reversed = slice.call(array).reverse(); + var reversed = slice(array).reverse(); reduce(reversed, memo, iteratee, callback); } diff --git a/lib/seq.js b/lib/seq.js index 9e86aca..ccdd277 100644 --- a/lib/seq.js +++ b/lib/seq.js @@ -1,5 +1,4 @@ import noop from 'lodash/noop'; -import rest from './internal/rest'; import slice from 'lodash/slice'; import reduce from './reduce'; import wrapAsync from './internal/wrapAsync'; @@ -43,9 +42,10 @@ import arrayMap from 'lodash/_arrayMap'; * }); * }); */ -export default rest(function seq(functions) { - var _functions = arrayMap(functions, wrapAsync); - return rest(function(args) { +export default function seq(/*...functions*/) { + var _functions = arrayMap(arguments, wrapAsync); + return function(/*...args*/) { + var args = slice(arguments); var that = this; var cb = args[args.length - 1]; @@ -56,7 +56,7 @@ export default rest(function seq(functions) { } reduce(_functions, args, function(newargs, fn, cb) { - fn.apply(that, newargs.concat(function(err/*, nextargs...*/) { + fn.apply(that, newargs.concat(function(err/*, ...nextargs*/) { var nextargs = slice(arguments, 1); cb(err, nextargs); })); @@ -64,5 +64,5 @@ export default rest(function seq(functions) { function(err, results) { cb.apply(that, [err].concat(results)); }); - }); -}) + }; +} -- cgit v1.2.1 From fddea479f798be3bdf598e10b13ede4ad516cd92 Mon Sep 17 00:00:00 2001 From: Alexander Early Date: Mon, 3 Apr 2017 01:21:50 -0700 Subject: fix deprecation warning --- perf/benchmark.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/perf/benchmark.js b/perf/benchmark.js index 42f400a..393464f 100755 --- a/perf/benchmark.js +++ b/perf/benchmark.js @@ -213,8 +213,7 @@ function cloneVersion(tag, callback) { fs.open(versionDir + "/package.json", "r", function (err, handle) { if (!err) { // version has already been cloned - fs.close(handle); - return callback(); + return fs.close(handle, callback); } var repoPath = path.join(__dirname, ".."); -- cgit v1.2.1 From a6bd3a00b505e2bc51d6f322387645aff61abf76 Mon Sep 17 00:00:00 2001 From: Alexander Early Date: Mon, 3 Apr 2017 22:38:41 -0700 Subject: replace lodash/slice --- lib/auto.js | 2 +- lib/seq.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/auto.js b/lib/auto.js index d712cc1..e2c0ab9 100644 --- a/lib/auto.js +++ b/lib/auto.js @@ -4,8 +4,8 @@ import indexOf from 'lodash/_baseIndexOf'; import isArray from 'lodash/isArray'; import okeys from 'lodash/keys'; import noop from 'lodash/noop'; -import slice from 'lodash/slice'; +import slice from './internal/slice'; import once from './internal/once'; import onlyOnce from './internal/onlyOnce'; import wrapAsync from './internal/wrapAsync'; diff --git a/lib/seq.js b/lib/seq.js index ccdd277..8d31e49 100644 --- a/lib/seq.js +++ b/lib/seq.js @@ -1,5 +1,5 @@ import noop from 'lodash/noop'; -import slice from 'lodash/slice'; +import slice from './internal/slice'; import reduce from './reduce'; import wrapAsync from './internal/wrapAsync'; import arrayMap from 'lodash/_arrayMap'; -- cgit v1.2.1 From 9b0f9eb1854cbc30960251a71ff8ce08bfa9dc0a Mon Sep 17 00:00:00 2001 From: Alexander Early Date: Mon, 3 Apr 2017 23:19:02 -0700 Subject: add a test for a unique waterfall fail case --- mocha_test/waterfall.js | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/mocha_test/waterfall.js b/mocha_test/waterfall.js index 0c21c80..54ca9f9 100644 --- a/mocha_test/waterfall.js +++ b/mocha_test/waterfall.js @@ -93,7 +93,6 @@ describe("waterfall", function () { it('multiple callback calls', function(){ var arr = [ function(callback){ - // call the callback twice. this should call function 2 twice callback(null, 'one', 'two'); callback(null, 'one', 'two'); }, @@ -106,6 +105,37 @@ describe("waterfall", function () { }).to.throw(/already called/); }); + it('multiple callback calls (trickier) @nodeonly', function(done){ + + // do a weird dance to catch the async thrown error before mocha + var listeners = process.listeners('uncaughtException'); + process.removeAllListeners('uncaughtException'); + process.once('uncaughtException', function onErr(err) { + listeners.forEach(function(listener) { + process.on('uncaughtException', listener); + }); + // can't throw errors in a uncaughtException handler, defer + setTimeout(checkErr, 0, err) + }) + + function checkErr(err) { + expect(err.message).to.match(/already called/); + done(); + } + + async.waterfall([ + function(callback){ + setTimeout(callback, 0, null, 'one', 'two'); + setTimeout(callback, 10, null, 'one', 'two'); + }, + function(arg1, arg2, callback){ + setTimeout(callback, 15, null, arg1, arg2, 'three'); + } + ], function () { + throw new Error('should not get here') + }); + }); + it('call in another context @nycinvalid @nodeonly', function(done) { var vm = require('vm'); var sandbox = { -- cgit v1.2.1 From dddb9f50a079580f938e69f1ba9d32927a08301c Mon Sep 17 00:00:00 2001 From: Alexander Early Date: Mon, 3 Apr 2017 23:45:58 -0700 Subject: fix ellipsis in comments --- lib/doDuring.js | 2 +- lib/doWhilst.js | 2 +- lib/whilst.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/doDuring.js b/lib/doDuring.js index 06aa21e..cce61d0 100644 --- a/lib/doDuring.js +++ b/lib/doDuring.js @@ -28,7 +28,7 @@ export default function doDuring(fn, test, callback) { var _fn = wrapAsync(fn); var _test = wrapAsync(test); - function next(err/*, args...*/) { + function next(err/*, ...args*/) { if (err) return callback(err); var args = slice(arguments, 1); args.push(check); diff --git a/lib/doWhilst.js b/lib/doWhilst.js index fa07874..5e7d259 100644 --- a/lib/doWhilst.js +++ b/lib/doWhilst.js @@ -29,7 +29,7 @@ import wrapAsync from './internal/wrapAsync'; export default function doWhilst(iteratee, test, callback) { callback = onlyOnce(callback || noop); var _iteratee = wrapAsync(iteratee); - var next = function(err/*, args...*/) { + var next = function(err/*, ...args*/) { if (err) return callback(err); var args = slice(arguments, 1); if (test.apply(this, args)) return _iteratee(next); diff --git a/lib/whilst.js b/lib/whilst.js index 5c8880f..5838b79 100644 --- a/lib/whilst.js +++ b/lib/whilst.js @@ -42,7 +42,7 @@ export default function whilst(test, iteratee, callback) { callback = onlyOnce(callback || noop); var _iteratee = wrapAsync(iteratee); if (!test()) return callback(null); - var next = function(err/*, args...*/) { + var next = function(err/*, ...args*/) { if (err) return callback(err); if (test()) return _iteratee(next); callback.apply(null, [null].concat(slice(arguments, 1))); -- cgit v1.2.1 From 53019a85063576c3aa7e48410d5f8018337f348e Mon Sep 17 00:00:00 2001 From: Alexander Early Date: Mon, 3 Apr 2017 23:46:20 -0700 Subject: simplify waterfall, commit built files --- dist/async.js | 256 ++++++++++++++++++++++------------------------------- dist/async.min.js | 2 +- dist/async.min.map | 2 +- lib/waterfall.js | 28 +++--- 4 files changed, 123 insertions(+), 165 deletions(-) diff --git a/dist/async.js b/dist/async.js index 4d2aa08..6d36974 100644 --- a/dist/async.js +++ b/dist/async.js @@ -4,59 +4,24 @@ (factory((global.async = global.async || {}))); }(this, (function (exports) { 'use strict'; -/** - * A faster alternative to `Function#apply`, this function invokes `func` - * with the `this` binding of `thisArg` and the arguments of `args`. - * - * @private - * @param {Function} func The function to invoke. - * @param {*} thisArg The `this` binding of `func`. - * @param {Array} args The arguments to invoke `func` with. - * @returns {*} Returns the result of `func`. - */ -function apply(func, thisArg, args) { - switch (args.length) { - case 0: return func.call(thisArg); - case 1: return func.call(thisArg, args[0]); - case 2: return func.call(thisArg, args[0], args[1]); - case 3: return func.call(thisArg, args[0], args[1], args[2]); - } - return func.apply(thisArg, args); -} - -/* Built-in method references for those with the same name as other `lodash` methods. */ -var nativeMax = Math.max; - -/** - * A specialized version of `baseRest` which transforms the rest array. - * - * @private - * @param {Function} func The function to apply a rest parameter to. - * @param {number} [start=func.length-1] The start position of the rest parameter. - * @param {Function} transform The rest array transform. - * @returns {Function} Returns the new function. - */ -function overRest$1(func, start, transform) { - start = nativeMax(start === undefined ? (func.length - 1) : start, 0); - return function() { - var args = arguments, - index = -1, - length = nativeMax(args.length - start, 0), - array = Array(length); - - while (++index < length) { - array[index] = args[start + index]; +function slice(arrayLike, start) { + start = start | 0; + var newLen = Math.max(arrayLike.length - start, 0); + var newArr = Array(newLen); + for (var idx = 0; idx < newLen; idx++) { + newArr[idx] = arrayLike[start + idx]; } - index = -1; - var otherArgs = Array(start + 1); - while (++index < start) { - otherArgs[index] = args[index]; - } - otherArgs[start] = transform(array); - return apply(func, this, otherArgs); - }; + return newArr; } +var initialParams = function (fn) { + return function () /*...args, callback*/{ + var args = slice(arguments); + var callback = args.pop(); + fn.call(this, args, callback); + }; +}; + /** * This method returns the first argument it receives. * @@ -77,19 +42,6 @@ function identity(value) { return value; } -// Lodash rest function without function.toString() -// remappings -function rest(func, start) { - return overRest$1(func, start, identity); -} - -var initialParams = function (fn) { - return rest(function (args /*..., callback*/) { - var callback = args.pop(); - fn.call(this, args, callback); - }); -}; - /** * Checks if `value` is the * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types) @@ -221,7 +173,8 @@ function wrapAsync(asyncFn) { var wrapAsync$1 = supportsAsync() ? wrapAsync : identity; function applyEach$1(eachfn) { - return rest(function (fns, args) { + return function (fns /*, ...args*/) { + var args = slice(arguments, 1); var go = initialParams(function (args, callback) { var that = this; return eachfn(fns, function (fn, cb) { @@ -233,7 +186,7 @@ function applyEach$1(eachfn) { } else { return go; } - }); + }; } /** Detect free variable `global` from Node.js. */ @@ -1264,10 +1217,11 @@ var applyEachSeries = applyEach$1(mapSeries); * @memberOf module:Utils * @method * @category Util - * @param {Function} function - The function you want to eventually apply all + * @param {Function} fn - The function you want to eventually apply all * arguments to. Invokes with (arguments...). * @param {...*} arguments... - Any number of arguments to automatically apply * when the continuation is called. + * @returns {Function} the partially-applied function * @example * * // using apply @@ -1296,11 +1250,13 @@ var applyEachSeries = applyEach$1(mapSeries); * two * three */ -var apply$2 = rest(function (fn, args) { - return rest(function (callArgs) { +var apply = function (fn /*, args*/) { + var args = slice(arguments, 1); + return function () /*callArgs*/{ + var callArgs = slice(arguments); return fn.apply(null, args.concat(callArgs)); - }); -}); + }; +}; /** * A specialized version of `_.forEach` for arrays without support for @@ -1620,26 +1576,26 @@ var auto = function (tasks, concurrency, callback) { function runTask(key, task) { if (hasError) return; - var taskCallback = onlyOnce(rest(function (err, args) { + var taskCallback = onlyOnce(function (err, result) { runningTasks--; - if (args.length <= 1) { - args = args[0]; + if (arguments.length > 2) { + result = slice(arguments, 1); } if (err) { var safeResults = {}; baseForOwn(results, function (val, rkey) { safeResults[rkey] = val; }); - safeResults[key] = args; + safeResults[key] = result; hasError = true; listeners = Object.create(null); callback(err, safeResults); } else { - results[key] = args; + results[key] = result; taskComplete(key); } - })); + }); runningTasks++; var taskFn = wrapAsync$1(task[task.length - 1]); @@ -2131,11 +2087,12 @@ function fallback(fn) { } function wrap(defer) { - return rest(function (fn, args) { + return function (fn /*, ...args*/) { + var args = slice(arguments, 1); defer(function () { fn.apply(null, args); }); - }); + }; } var _defer; @@ -2249,7 +2206,7 @@ function queue(worker, concurrency, payload) { } function _next(tasks) { - return rest(function (args) { + return function (err) { numRunning -= 1; for (var i = 0, l = tasks.length; i < l; i++) { @@ -2259,10 +2216,10 @@ function queue(worker, concurrency, payload) { workersList.splice(index); } - task.callback.apply(task, args); + task.callback.apply(task, arguments); - if (args[0] != null) { - q.error(args[0], task.data); + if (err != null) { + q.error(err, task.data); } } @@ -2274,7 +2231,7 @@ function queue(worker, concurrency, payload) { q.drain(); } q.process(); - }); + }; } var isProcessing = false; @@ -2318,11 +2275,12 @@ function queue(worker, concurrency, payload) { data.push(node.data); } + numRunning += 1; + workersList.push(tasks[0]); + if (q._tasks.length === 0) { q.empty(); } - numRunning += 1; - workersList.push(tasks[0]); if (numRunning === q.concurrency) { q.saturated(); @@ -2550,9 +2508,10 @@ function reduce(coll, memo, iteratee, callback) { * }); * }); */ -var seq$1 = rest(function seq(functions) { - var _functions = arrayMap(functions, wrapAsync$1); - return rest(function (args) { +function seq() /*...functions*/{ + var _functions = arrayMap(arguments, wrapAsync$1); + return function () /*...args*/{ + var args = slice(arguments); var that = this; var cb = args[args.length - 1]; @@ -2563,14 +2522,15 @@ var seq$1 = rest(function seq(functions) { } reduce(_functions, args, function (newargs, fn, cb) { - fn.apply(that, newargs.concat(rest(function (err, nextargs) { + fn.apply(that, newargs.concat(function (err /*, ...nextargs*/) { + var nextargs = slice(arguments, 1); cb(err, nextargs); - }))); + })); }, function (err, results) { cb.apply(that, [err].concat(results)); }); - }); -}); + }; +} /** * Creates a function which is a composition of the passed asynchronous @@ -2607,9 +2567,9 @@ var seq$1 = rest(function seq(functions) { * // result now equals 15 * }); */ -var compose = rest(function (args) { - return seq$1.apply(null, args.reverse()); -}); +var compose = function () /*...args*/{ + return seq.apply(null, slice(arguments).reverse()); +}; function concat$1(eachfn, arr, fn, callback) { var result = []; @@ -2718,12 +2678,14 @@ var concatSeries = doSeries(concat$1); * //... * }, callback); */ -var constant = rest(function (values) { +var constant = function () /*...values*/{ + var values = slice(arguments); var args = [null].concat(values); - return initialParams(function (ignoredArgs, callback) { + return function () /*...ignoredArgs, callback*/{ + var callback = arguments[arguments.length - 1]; return callback.apply(this, args); - }); -}); + }; +}; function _createTester(check, getResult) { return function (eachfn, arr, iteratee, cb) { @@ -2840,8 +2802,10 @@ var detectLimit = doParallelLimit(_createTester(identity, _findGetResult)); var detectSeries = doLimit(detectLimit, 1); function consoleFunc(name) { - return rest(function (fn, args) { - wrapAsync$1(fn).apply(null, args.concat(rest(function (err, args) { + return function (fn /*, ...args*/) { + var args = slice(arguments, 1); + wrapAsync$1(fn).apply(null, args.concat(function (err /*, ...args*/) { + var args = slice(arguments, 1); if (typeof console === 'object') { if (err) { if (console.error) { @@ -2853,8 +2817,8 @@ function consoleFunc(name) { }); } } - }))); - }); + })); + }; } /** @@ -2913,11 +2877,12 @@ function doDuring(fn, test, callback) { var _fn = wrapAsync$1(fn); var _test = wrapAsync$1(test); - var next = rest(function (err, args) { + function next(err /*, ...args*/) { if (err) return callback(err); + var args = slice(arguments, 1); args.push(check); _test.apply(this, args); - }); + } function check(err, truth) { if (err) return callback(err); @@ -2953,11 +2918,12 @@ function doDuring(fn, test, callback) { function doWhilst(iteratee, test, callback) { callback = onlyOnce(callback || noop); var _iteratee = wrapAsync$1(iteratee); - var next = rest(function (err, args) { + var next = function (err /*, ...args*/) { if (err) return callback(err); + var args = slice(arguments, 1); if (test.apply(this, args)) return _iteratee(next); callback.apply(null, [null].concat(args)); - }); + }; _iteratee(next); } @@ -3750,14 +3716,15 @@ function memoize(fn, hasher) { queues[key].push(callback); } else { queues[key] = [callback]; - _fn.apply(null, args.concat(rest(function (args) { + _fn.apply(null, args.concat(function () /*args*/{ + var args = slice(arguments); memo[key] = args; var q = queues[key]; delete queues[key]; for (var i = 0, l = q.length; i < l; i++) { q[i].apply(null, args); } - }))); + })); } }); memoized.memo = memo; @@ -3813,13 +3780,13 @@ function _parallel(eachfn, tasks, callback) { var results = isArrayLike(tasks) ? [] : {}; eachfn(tasks, function (task, key, callback) { - wrapAsync$1(task)(rest(function (err, args) { - if (args.length <= 1) { - args = args[0]; + wrapAsync$1(task)(function (err, result) { + if (arguments.length > 2) { + result = slice(arguments, 1); } - results[key] = args; + results[key] = result; callback(err); - })); + }); }, function (err) { callback(err, results); }); @@ -4143,8 +4110,6 @@ function race(tasks, callback) { } } -var slice = Array.prototype.slice; - /** * Same as [`reduce`]{@link module:Collections.reduce}, only operates on `array` in reverse order. * @@ -4168,7 +4133,7 @@ var slice = Array.prototype.slice; * (err, result). */ function reduceRight(array, memo, iteratee, callback) { - var reversed = slice.call(array).reverse(); + var reversed = slice(array).reverse(); reduce(reversed, memo, iteratee, callback); } @@ -4214,23 +4179,19 @@ function reduceRight(array, memo, iteratee, callback) { function reflect(fn) { var _fn = wrapAsync$1(fn); return initialParams(function reflectOn(args, reflectCallback) { - args.push(rest(function callback(err, cbArgs) { + args.push(function callback(err, cbArg) { if (err) { reflectCallback(null, { error: err }); } else { - var value = null; - if (cbArgs.length === 1) { - value = cbArgs[0]; - } else if (cbArgs.length > 1) { - value = cbArgs; - } + var value = cbArg; + if (arguments.length > 2) value = slice(arguments, 1); reflectCallback(null, { value: value }); } - })); + }); return _fn.apply(this, args); }); @@ -4882,7 +4843,7 @@ function timeout(asyncFn, milliseconds, info) { /* Built-in method references for those with the same name as other `lodash` methods. */ var nativeCeil = Math.ceil; -var nativeMax$1 = Math.max; +var nativeMax = Math.max; /** * The base implementation of `_.range` and `_.rangeRight` which doesn't @@ -4897,7 +4858,7 @@ var nativeMax$1 = Math.max; */ function baseRange(start, end, step, fromRight) { var index = -1, - length = nativeMax$1(nativeCeil((end - start) / (step || 1)), 0), + length = nativeMax(nativeCeil((end - start) / (step || 1)), 0), result = Array(length); while (length--) { @@ -5093,11 +5054,11 @@ function whilst(test, iteratee, callback) { callback = onlyOnce(callback || noop); var _iteratee = wrapAsync$1(iteratee); if (!test()) return callback(null); - var next = rest(function (err, args) { + var next = function (err /*, ...args*/) { if (err) return callback(err); if (test()) return _iteratee(next); - callback.apply(null, [null].concat(args)); - }); + callback.apply(null, [null].concat(slice(arguments, 1))); + }; _iteratee(next); } @@ -5191,26 +5152,25 @@ var waterfall = function (tasks, callback) { if (!isArray(tasks)) return callback(new Error('First argument to waterfall must be an array of functions')); if (!tasks.length) return callback(); var taskIndex = 0; + var args = []; - function nextTask(args) { - if (taskIndex === tasks.length) { - return callback.apply(null, [null].concat(args)); - } - - var taskCallback = onlyOnce(rest(function (err, args) { - if (err) { - return callback.apply(null, [err].concat(args)); - } - nextTask(args); - })); - + function nextTask() { + var task = wrapAsync$1(tasks[taskIndex++]); + var taskCallback = onlyOnce(next); args.push(taskCallback); - var task = wrapAsync$1(tasks[taskIndex++]); task.apply(null, args); } - nextTask([]); + function next(err /*, ...args*/) { + if (err || taskIndex === tasks.length) { + return callback.apply(null, arguments); + } + args = slice(arguments, 1); + nextTask(); + } + + nextTask(); }; /** @@ -5280,7 +5240,7 @@ var waterfall = function (tasks, callback) { var index = { applyEach: applyEach, applyEachSeries: applyEachSeries, - apply: apply$2, + apply: apply, asyncify: asyncify, auto: auto, autoInject: autoInject, @@ -5337,7 +5297,7 @@ var index = { rejectSeries: rejectSeries, retry: retry, retryable: retryable, - seq: seq$1, + seq: seq, series: series, setImmediate: setImmediate$1, some: some, @@ -5375,7 +5335,7 @@ var index = { exports['default'] = index; exports.applyEach = applyEach; exports.applyEachSeries = applyEachSeries; -exports.apply = apply$2; +exports.apply = apply; exports.asyncify = asyncify; exports.auto = auto; exports.autoInject = autoInject; @@ -5432,7 +5392,7 @@ exports.rejectLimit = rejectLimit; exports.rejectSeries = rejectSeries; exports.retry = retry; exports.retryable = retryable; -exports.seq = seq$1; +exports.seq = seq; exports.series = series; exports.setImmediate = setImmediate$1; exports.some = some; diff --git a/dist/async.min.js b/dist/async.min.js index afd1022..65fe89c 100644 --- a/dist/async.min.js +++ b/dist/async.min.js @@ -1,2 +1,2 @@ -!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t(e.async=e.async||{})}(this,function(exports){"use strict";function apply(e,t,r){switch(r.length){case 0:return e.call(t);case 1:return e.call(t,r[0]);case 2:return e.call(t,r[0],r[1]);case 3:return e.call(t,r[0],r[1],r[2])}return e.apply(t,r)}function overRest$1(e,t,r){return t=nativeMax(void 0===t?e.length-1:t,0),function(){for(var n=arguments,o=-1,i=nativeMax(n.length-t,0),a=Array(i);++o-1&&e%1==0&&e<=MAX_SAFE_INTEGER}function isArrayLike(e){return null!=e&&isLength(e.length)&&!isFunction(e)}function noop(){}function once(e){return function(){if(null!==e){var t=e;e=null,t.apply(this,arguments)}}}function baseTimes(e,t){for(var r=-1,n=Array(e);++r-1&&e%1==0&&eo?0:o+t),r=r>o?o:r,r<0&&(r+=o),o=t>r?0:r-t>>>0,t>>>=0;for(var i=Array(o);++n=n?e:baseSlice(e,t,r)}function charsEndIndex(e,t){for(var r=e.length;r--&&baseIndexOf(t,e[r],0)>-1;);return r}function charsStartIndex(e,t){for(var r=-1,n=e.length;++r-1;);return r}function asciiToArray(e){return e.split("")}function hasUnicode(e){return reHasUnicode.test(e)}function unicodeToArray(e){return e.match(reUnicode)||[]}function stringToArray(e){return hasUnicode(e)?unicodeToArray(e):asciiToArray(e)}function toString(e){return null==e?"":baseToString(e)}function trim(e,t,r){if(e=toString(e),e&&(r||void 0===t))return e.replace(reTrim,"");if(!e||!(t=baseToString(t)))return e;var n=stringToArray(e),o=stringToArray(t),i=charsStartIndex(n,o),a=charsEndIndex(n,o)+1;return castSlice(n,i,a).join("")}function parseParams(e){return e=e.toString().replace(STRIP_COMMENTS,""),e=e.match(FN_ARGS)[2].replace(" ",""),e=e?e.split(FN_ARG_SPLIT):[],e=e.map(function(e){return trim(e.replace(FN_ARG,""))})}function autoInject(e,t){var r={};baseForOwn(e,function(e,t){function n(t,r){var n=arrayMap(o,function(e){return t[e]});n.push(r),wrapAsync$1(e).apply(null,n)}var o,i=isAsync(e),a=!i&&1===e.length||i&&0===e.length;if(isArray(e))o=e.slice(0,-1),e=e[e.length-1],r[t]=o.concat(o.length>0?n:e);else if(a)r[t]=e;else{if(o=parseParams(e),0===e.length&&!i&&0===o.length)throw new Error("autoInject task functions require explicit parameters.");i||o.pop(),r[t]=o.concat(n)}}),auto(r,t)}function fallback(e){setTimeout(e,0)}function wrap(e){return rest(function(t,r){e(function(){t.apply(null,r)})})}function DLL(){this.head=this.tail=null,this.length=0}function setInitial(e,t){e.length=1,e.head=e.tail=t}function queue(e,t,r){function n(e,t,r){if(null!=r&&"function"!=typeof r)throw new Error("task callback must be a function");if(u.started=!0,isArray(e)||(e=[e]),0===e.length&&u.idle())return setImmediate$1(function(){u.drain()});for(var n=0,o=e.length;n=0&&s.splice(i),o.callback.apply(o,t),null!=t[0]&&u.error(t[0],o.data)}a<=u.concurrency-u.buffer&&u.unsaturated(),u.idle()&&u.drain(),u.process()})}if(null==t)t=1;else if(0===t)throw new Error("Concurrency must not be zero");var i=wrapAsync$1(e),a=0,s=[],c=!1,u={_tasks:new DLL,concurrency:t,payload:r,saturated:noop,unsaturated:noop,buffer:t/4,empty:noop,drain:noop,error:noop,started:!1,paused:!1,push:function(e,t){n(e,!1,t)},kill:function(){u.drain=noop,u._tasks.empty()},unshift:function(e,t){n(e,!0,t)},process:function(){if(!c){for(c=!0;!u.paused&&a1&&(n=t),r(null,{value:n})}})),t.apply(this,e)})}function reject$1(e,t,r,n){_filter(e,t,function(e,t){r(e,function(e,r){t(e,!r)})},n)}function reflectAll(e){var t;return isArray(e)?t=arrayMap(e,reflect):(t={},baseForOwn(e,function(e,r){t[r]=reflect.call(this,e)})),t}function constant$1(e){return function(){return e}}function retry(e,t,r){function n(e,t){if("object"==typeof t)e.times=+t.times||i,e.intervalFunc="function"==typeof t.interval?t.interval:constant$1(+t.interval||a),e.errorFilter=t.errorFilter;else{if("number"!=typeof t&&"string"!=typeof t)throw new Error("Invalid arguments for async.retry");e.times=+t||i}}function o(){c(function(e){e&&u++n?1:0}var o=wrapAsync$1(t);map(e,function(e,t){o(e,function(r,n){return r?t(r):void t(null,{value:e,criteria:n})})},function(e,t){return e?r(e):void r(null,arrayMap(t.sort(n),baseProperty("value")))})}function timeout(e,t,r){function n(){s||(i.apply(null,arguments),clearTimeout(a))}function o(){var t=e.name||"anonymous",n=new Error('Callback function "'+t+'" timed out.');n.code="ETIMEDOUT",r&&(n.info=r),s=!0,i(n)}var i,a,s=!1,c=wrapAsync$1(e);return initialParams(function(e,r){i=r,a=setTimeout(o,t),c.apply(null,e.concat(n))})}function baseRange(e,t,r,n){for(var o=-1,i=nativeMax$1(nativeCeil((t-e)/(r||1)),0),a=Array(i);i--;)a[n?i:++o]=e,e+=r;return a}function timeLimit(e,t,r,n){var o=wrapAsync$1(r);mapLimit(baseRange(0,e,1),t,o,n)}function transform(e,t,r,n){arguments.length<=3&&(n=r,r=t,t=isArray(e)?[]:{}),n=once(n||noop);var o=wrapAsync$1(r);eachOf(e,function(e,r,n){o(t,e,r,n)},function(e){n(e,t)})}function unmemoize(e){return function(){return(e.unmemoized||e).apply(null,arguments)}}function whilst(e,t,r){r=onlyOnce(r||noop);var n=wrapAsync$1(t);if(!e())return r(null);var o=rest(function(t,i){return t?r(t):e()?n(o):void r.apply(null,[null].concat(i))});n(o)}function until(e,t,r){whilst(function(){return!e.apply(this,arguments)},t,r)}var nativeMax=Math.max,initialParams=function(e){return rest(function(t){var r=t.pop();e.call(this,t,r)})},supportsSymbol="function"==typeof Symbol,wrapAsync$1=supportsAsync()?wrapAsync:identity,freeGlobal="object"==typeof global&&global&&global.Object===Object&&global,freeSelf="object"==typeof self&&self&&self.Object===Object&&self,root=freeGlobal||freeSelf||Function("return this")(),Symbol$1=root.Symbol,objectProto=Object.prototype,hasOwnProperty=objectProto.hasOwnProperty,nativeObjectToString=objectProto.toString,symToStringTag$1=Symbol$1?Symbol$1.toStringTag:void 0,objectProto$1=Object.prototype,nativeObjectToString$1=objectProto$1.toString,nullTag="[object Null]",undefinedTag="[object Undefined]",symToStringTag=Symbol$1?Symbol$1.toStringTag:void 0,asyncTag="[object AsyncFunction]",funcTag="[object Function]",genTag="[object GeneratorFunction]",proxyTag="[object Proxy]",MAX_SAFE_INTEGER=9007199254740991,breakLoop={},iteratorSymbol="function"==typeof Symbol&&Symbol.iterator,getIterator=function(e){return iteratorSymbol&&e[iteratorSymbol]&&e[iteratorSymbol]()},argsTag="[object Arguments]",objectProto$3=Object.prototype,hasOwnProperty$2=objectProto$3.hasOwnProperty,propertyIsEnumerable=objectProto$3.propertyIsEnumerable,isArguments=baseIsArguments(function(){return arguments}())?baseIsArguments:function(e){return isObjectLike(e)&&hasOwnProperty$2.call(e,"callee")&&!propertyIsEnumerable.call(e,"callee")},isArray=Array.isArray,freeExports="object"==typeof exports&&exports&&!exports.nodeType&&exports,freeModule=freeExports&&"object"==typeof module&&module&&!module.nodeType&&module,moduleExports=freeModule&&freeModule.exports===freeExports,Buffer=moduleExports?root.Buffer:void 0,nativeIsBuffer=Buffer?Buffer.isBuffer:void 0,isBuffer=nativeIsBuffer||stubFalse,MAX_SAFE_INTEGER$1=9007199254740991,reIsUint=/^(?:0|[1-9]\d*)$/,argsTag$1="[object Arguments]",arrayTag="[object Array]",boolTag="[object Boolean]",dateTag="[object Date]",errorTag="[object Error]",funcTag$1="[object Function]",mapTag="[object Map]",numberTag="[object Number]",objectTag="[object Object]",regexpTag="[object RegExp]",setTag="[object Set]",stringTag="[object String]",weakMapTag="[object WeakMap]",arrayBufferTag="[object ArrayBuffer]",dataViewTag="[object DataView]",float32Tag="[object Float32Array]",float64Tag="[object Float64Array]",int8Tag="[object Int8Array]",int16Tag="[object Int16Array]",int32Tag="[object Int32Array]",uint8Tag="[object Uint8Array]",uint8ClampedTag="[object Uint8ClampedArray]",uint16Tag="[object Uint16Array]",uint32Tag="[object Uint32Array]",typedArrayTags={};typedArrayTags[float32Tag]=typedArrayTags[float64Tag]=typedArrayTags[int8Tag]=typedArrayTags[int16Tag]=typedArrayTags[int32Tag]=typedArrayTags[uint8Tag]=typedArrayTags[uint8ClampedTag]=typedArrayTags[uint16Tag]=typedArrayTags[uint32Tag]=!0,typedArrayTags[argsTag$1]=typedArrayTags[arrayTag]=typedArrayTags[arrayBufferTag]=typedArrayTags[boolTag]=typedArrayTags[dataViewTag]=typedArrayTags[dateTag]=typedArrayTags[errorTag]=typedArrayTags[funcTag$1]=typedArrayTags[mapTag]=typedArrayTags[numberTag]=typedArrayTags[objectTag]=typedArrayTags[regexpTag]=typedArrayTags[setTag]=typedArrayTags[stringTag]=typedArrayTags[weakMapTag]=!1;var freeExports$1="object"==typeof exports&&exports&&!exports.nodeType&&exports,freeModule$1=freeExports$1&&"object"==typeof module&&module&&!module.nodeType&&module,moduleExports$1=freeModule$1&&freeModule$1.exports===freeExports$1,freeProcess=moduleExports$1&&freeGlobal.process,nodeUtil=function(){try{return freeProcess&&freeProcess.binding("util")}catch(e){}}(),nodeIsTypedArray=nodeUtil&&nodeUtil.isTypedArray,isTypedArray=nodeIsTypedArray?baseUnary(nodeIsTypedArray):baseIsTypedArray,objectProto$2=Object.prototype,hasOwnProperty$1=objectProto$2.hasOwnProperty,objectProto$5=Object.prototype,nativeKeys=overArg(Object.keys,Object),objectProto$4=Object.prototype,hasOwnProperty$3=objectProto$4.hasOwnProperty,eachOfGeneric=doLimit(eachOfLimit,1/0),eachOf=function(e,t,r){var n=isArrayLike(e)?eachOfArrayLike:eachOfGeneric;n(e,wrapAsync$1(t),r)},map=doParallel(_asyncMap),applyEach=applyEach$1(map),mapLimit=doParallelLimit(_asyncMap),mapSeries=doLimit(mapLimit,1),applyEachSeries=applyEach$1(mapSeries),apply$2=rest(function(e,t){return rest(function(r){return e.apply(null,t.concat(r))})}),baseFor=createBaseFor(),auto=function(e,t,r){function n(e,t){g.push(function(){s(e,t)})}function o(){if(0===g.length&&0===y)return r(null,p);for(;g.length&&y1?o(p,n):o(n)}}function c(){for(var e,t=0;h.length;)e=h.pop(),t++,arrayEach(u(e),function(e){0===--b[e]&&h.push(e)});if(t!==f)throw new Error("async.auto cannot execute tasks due to a recursive dependency")}function u(t){var r=[];return baseForOwn(e,function(e,n){isArray(e)&&baseIndexOf(e,t,0)>=0&&r.push(n)}),r}"function"==typeof t&&(r=t,t=null),r=once(r||noop);var l=keys(e),f=l.length;if(!f)return r(null);t||(t=f);var p={},y=0,m=!1,d=Object.create(null),g=[],h=[],b={};baseForOwn(e,function(t,r){if(!isArray(t))return n(r,[t]),void h.push(r);var o=t.slice(0,t.length-1),a=o.length;return 0===a?(n(r,t),void h.push(r)):(b[r]=a,void arrayEach(o,function(s){if(!e[s])throw new Error("async.auto task `"+r+"` has a non-existent dependency `"+s+"` in "+o.join(", "));i(s,function(){a--,0===a&&n(r,t)})}))}),c(),o()},symbolTag="[object Symbol]",INFINITY=1/0,symbolProto=Symbol$1?Symbol$1.prototype:void 0,symbolToString=symbolProto?symbolProto.toString:void 0,rsAstralRange="\\ud800-\\udfff",rsComboMarksRange="\\u0300-\\u036f\\ufe20-\\ufe23",rsComboSymbolsRange="\\u20d0-\\u20f0",rsVarRange="\\ufe0e\\ufe0f",rsZWJ="\\u200d",reHasUnicode=RegExp("["+rsZWJ+rsAstralRange+rsComboMarksRange+rsComboSymbolsRange+rsVarRange+"]"),rsAstralRange$1="\\ud800-\\udfff",rsComboMarksRange$1="\\u0300-\\u036f\\ufe20-\\ufe23",rsComboSymbolsRange$1="\\u20d0-\\u20f0",rsVarRange$1="\\ufe0e\\ufe0f",rsAstral="["+rsAstralRange$1+"]",rsCombo="["+rsComboMarksRange$1+rsComboSymbolsRange$1+"]",rsFitz="\\ud83c[\\udffb-\\udfff]",rsModifier="(?:"+rsCombo+"|"+rsFitz+")",rsNonAstral="[^"+rsAstralRange$1+"]",rsRegional="(?:\\ud83c[\\udde6-\\uddff]){2}",rsSurrPair="[\\ud800-\\udbff][\\udc00-\\udfff]",rsZWJ$1="\\u200d",reOptMod=rsModifier+"?",rsOptVar="["+rsVarRange$1+"]?",rsOptJoin="(?:"+rsZWJ$1+"(?:"+[rsNonAstral,rsRegional,rsSurrPair].join("|")+")"+rsOptVar+reOptMod+")*",rsSeq=rsOptVar+reOptMod+rsOptJoin,rsSymbol="(?:"+[rsNonAstral+rsCombo+"?",rsCombo,rsRegional,rsSurrPair,rsAstral].join("|")+")",reUnicode=RegExp(rsFitz+"(?="+rsFitz+")|"+rsSymbol+rsSeq,"g"),reTrim=/^\s+|\s+$/g,FN_ARGS=/^(?:async\s+)?(function)?\s*[^\(]*\(\s*([^\)]*)\)/m,FN_ARG_SPLIT=/,/,FN_ARG=/(=.+)?(\s*)$/,STRIP_COMMENTS=/((\/\/.*$)|(\/\*[\s\S]*?\*\/))/gm,hasSetImmediate="function"==typeof setImmediate&&setImmediate,hasNextTick="object"==typeof process&&"function"==typeof process.nextTick,_defer;_defer=hasSetImmediate?setImmediate:hasNextTick?process.nextTick:fallback;var setImmediate$1=wrap(_defer);DLL.prototype.removeLink=function(e){return e.prev?e.prev.next=e.next:this.head=e.next,e.next?e.next.prev=e.prev:this.tail=e.prev,e.prev=e.next=null,this.length-=1,e},DLL.prototype.empty=DLL,DLL.prototype.insertAfter=function(e,t){t.prev=e,t.next=e.next,e.next?e.next.prev=t:this.tail=t,e.next=t,this.length+=1},DLL.prototype.insertBefore=function(e,t){t.prev=e.prev,t.next=e,e.prev?e.prev.next=t:this.head=t,e.prev=t,this.length+=1},DLL.prototype.unshift=function(e){this.head?this.insertBefore(this.head,e):setInitial(this,e)},DLL.prototype.push=function(e){this.tail?this.insertAfter(this.tail,e):setInitial(this,e)},DLL.prototype.shift=function(){return this.head&&this.removeLink(this.head)},DLL.prototype.pop=function(){return this.tail&&this.removeLink(this.tail)};var eachOfSeries=doLimit(eachOfLimit,1),seq$1=rest(function(e){var t=arrayMap(e,wrapAsync$1);return rest(function(e){var r=this,n=e[e.length-1];"function"==typeof n?e.pop():n=noop,reduce(t,e,function(e,t,n){t.apply(r,e.concat(rest(function(e,t){n(e,t)})))},function(e,t){n.apply(r,[e].concat(t))})})}),compose=rest(function(e){return seq$1.apply(null,e.reverse())}),concat=doParallel(concat$1),concatSeries=doSeries(concat$1),constant=rest(function(e){var t=[null].concat(e);return initialParams(function(e,r){return r.apply(this,t)})}),detect=doParallel(_createTester(identity,_findGetResult)),detectLimit=doParallelLimit(_createTester(identity,_findGetResult)),detectSeries=doLimit(detectLimit,1),dir=consoleFunc("dir"),eachSeries=doLimit(eachLimit$1,1),every=doParallel(_createTester(notId,notId)),everyLimit=doParallelLimit(_createTester(notId,notId)),everySeries=doLimit(everyLimit,1),filter=doParallel(_filter),filterLimit=doParallelLimit(_filter),filterSeries=doLimit(filterLimit,1),groupByLimit=function(e,t,r,n){n=n||noop;var o=wrapAsync$1(r);mapLimit(e,t,function(e,t){o(e,function(r,n){return r?t(r):t(null,{key:n,val:e})})},function(e,t){for(var r={},o=Object.prototype.hasOwnProperty,i=0;i=o.priority;)o=o.next;for(var i=0,a=e.length;i-1&&e%1==0&&e<=MAX_SAFE_INTEGER}function isArrayLike(e){return null!=e&&isLength(e.length)&&!isFunction(e)}function noop(){}function once(e){return function(){if(null!==e){var t=e;e=null,t.apply(this,arguments)}}}function baseTimes(e,t){for(var r=-1,n=Array(e);++r-1&&e%1==0&&ei?0:i+t),r=r>i?i:r,r<0&&(r+=i),i=t>r?0:r-t>>>0,t>>>=0;for(var o=Array(i);++n=n?e:baseSlice(e,t,r)}function charsEndIndex(e,t){for(var r=e.length;r--&&baseIndexOf(t,e[r],0)>-1;);return r}function charsStartIndex(e,t){for(var r=-1,n=e.length;++r-1;);return r}function asciiToArray(e){return e.split("")}function hasUnicode(e){return reHasUnicode.test(e)}function unicodeToArray(e){return e.match(reUnicode)||[]}function stringToArray(e){return hasUnicode(e)?unicodeToArray(e):asciiToArray(e)}function toString(e){return null==e?"":baseToString(e)}function trim(e,t,r){if(e=toString(e),e&&(r||void 0===t))return e.replace(reTrim,"");if(!e||!(t=baseToString(t)))return e;var n=stringToArray(e),i=stringToArray(t),o=charsStartIndex(n,i),a=charsEndIndex(n,i)+1;return castSlice(n,o,a).join("")}function parseParams(e){return e=e.toString().replace(STRIP_COMMENTS,""),e=e.match(FN_ARGS)[2].replace(" ",""),e=e?e.split(FN_ARG_SPLIT):[],e=e.map(function(e){return trim(e.replace(FN_ARG,""))})}function autoInject(e,t){var r={};baseForOwn(e,function(e,t){function n(t,r){var n=arrayMap(i,function(e){return t[e]});n.push(r),wrapAsync$1(e).apply(null,n)}var i,o=isAsync(e),a=!o&&1===e.length||o&&0===e.length;if(isArray(e))i=e.slice(0,-1),e=e[e.length-1],r[t]=i.concat(i.length>0?n:e);else if(a)r[t]=e;else{if(i=parseParams(e),0===e.length&&!o&&0===i.length)throw new Error("autoInject task functions require explicit parameters.");o||i.pop(),r[t]=i.concat(n)}}),auto(r,t)}function fallback(e){setTimeout(e,0)}function wrap(e){return function(t){var r=slice(arguments,1);e(function(){t.apply(null,r)})}}function DLL(){this.head=this.tail=null,this.length=0}function setInitial(e,t){e.length=1,e.head=e.tail=t}function queue(e,t,r){function n(e,t,r){if(null!=r&&"function"!=typeof r)throw new Error("task callback must be a function");if(u.started=!0,isArray(e)||(e=[e]),0===e.length&&u.idle())return setImmediate$1(function(){u.drain()});for(var n=0,i=e.length;n=0&&s.splice(o),i.callback.apply(i,arguments),null!=t&&u.error(t,i.data)}a<=u.concurrency-u.buffer&&u.unsaturated(),u.idle()&&u.drain(),u.process()}}if(null==t)t=1;else if(0===t)throw new Error("Concurrency must not be zero");var o=wrapAsync$1(e),a=0,s=[],c=!1,u={_tasks:new DLL,concurrency:t,payload:r,saturated:noop,unsaturated:noop,buffer:t/4,empty:noop,drain:noop,error:noop,started:!1,paused:!1,push:function(e,t){n(e,!1,t)},kill:function(){u.drain=noop,u._tasks.empty()},unshift:function(e,t){n(e,!0,t)},process:function(){if(!c){for(c=!0;!u.paused&&a2&&(i=slice(arguments,1)),n[t]=i,r(e)})},function(e){r(e,n)})}function parallelLimit(e,t){_parallel(eachOf,e,t)}function parallelLimit$1(e,t,r){_parallel(_eachOfLimit(t),e,r)}function race(e,t){if(t=once(t||noop),!isArray(e))return t(new TypeError("First argument to race must be an array of functions"));if(!e.length)return t();for(var r=0,n=e.length;r2&&(n=slice(arguments,1)),r(null,{value:n})}}),t.apply(this,e)})}function reject$1(e,t,r,n){_filter(e,t,function(e,t){r(e,function(e,r){t(e,!r)})},n)}function reflectAll(e){var t;return isArray(e)?t=arrayMap(e,reflect):(t={},baseForOwn(e,function(e,r){t[r]=reflect.call(this,e)})),t}function constant$1(e){return function(){return e}}function retry(e,t,r){function n(e,t){if("object"==typeof t)e.times=+t.times||o,e.intervalFunc="function"==typeof t.interval?t.interval:constant$1(+t.interval||a),e.errorFilter=t.errorFilter;else{if("number"!=typeof t&&"string"!=typeof t)throw new Error("Invalid arguments for async.retry");e.times=+t||o}}function i(){c(function(e){e&&u++n?1:0}var i=wrapAsync$1(t);map(e,function(e,t){i(e,function(r,n){return r?t(r):void t(null,{value:e,criteria:n})})},function(e,t){return e?r(e):void r(null,arrayMap(t.sort(n),baseProperty("value")))})}function timeout(e,t,r){function n(){s||(o.apply(null,arguments),clearTimeout(a))}function i(){var t=e.name||"anonymous",n=new Error('Callback function "'+t+'" timed out.');n.code="ETIMEDOUT",r&&(n.info=r),s=!0,o(n)}var o,a,s=!1,c=wrapAsync$1(e);return initialParams(function(e,r){o=r,a=setTimeout(i,t),c.apply(null,e.concat(n))})}function baseRange(e,t,r,n){for(var i=-1,o=nativeMax(nativeCeil((t-e)/(r||1)),0),a=Array(o);o--;)a[n?o:++i]=e,e+=r;return a}function timeLimit(e,t,r,n){var i=wrapAsync$1(r);mapLimit(baseRange(0,e,1),t,i,n)}function transform(e,t,r,n){arguments.length<=3&&(n=r,r=t,t=isArray(e)?[]:{}),n=once(n||noop);var i=wrapAsync$1(r);eachOf(e,function(e,r,n){i(t,e,r,n)},function(e){n(e,t)})}function unmemoize(e){return function(){return(e.unmemoized||e).apply(null,arguments)}}function whilst(e,t,r){r=onlyOnce(r||noop);var n=wrapAsync$1(t);if(!e())return r(null);var i=function(t){return t?r(t):e()?n(i):void r.apply(null,[null].concat(slice(arguments,1)))};n(i)}function until(e,t,r){whilst(function(){return!e.apply(this,arguments)},t,r)}var initialParams=function(e){return function(){var t=slice(arguments),r=t.pop();e.call(this,t,r)}},supportsSymbol="function"==typeof Symbol,wrapAsync$1=supportsAsync()?wrapAsync:identity,freeGlobal="object"==typeof global&&global&&global.Object===Object&&global,freeSelf="object"==typeof self&&self&&self.Object===Object&&self,root=freeGlobal||freeSelf||Function("return this")(),Symbol$1=root.Symbol,objectProto=Object.prototype,hasOwnProperty=objectProto.hasOwnProperty,nativeObjectToString=objectProto.toString,symToStringTag$1=Symbol$1?Symbol$1.toStringTag:void 0,objectProto$1=Object.prototype,nativeObjectToString$1=objectProto$1.toString,nullTag="[object Null]",undefinedTag="[object Undefined]",symToStringTag=Symbol$1?Symbol$1.toStringTag:void 0,asyncTag="[object AsyncFunction]",funcTag="[object Function]",genTag="[object GeneratorFunction]",proxyTag="[object Proxy]",MAX_SAFE_INTEGER=9007199254740991,breakLoop={},iteratorSymbol="function"==typeof Symbol&&Symbol.iterator,getIterator=function(e){return iteratorSymbol&&e[iteratorSymbol]&&e[iteratorSymbol]()},argsTag="[object Arguments]",objectProto$3=Object.prototype,hasOwnProperty$2=objectProto$3.hasOwnProperty,propertyIsEnumerable=objectProto$3.propertyIsEnumerable,isArguments=baseIsArguments(function(){return arguments}())?baseIsArguments:function(e){return isObjectLike(e)&&hasOwnProperty$2.call(e,"callee")&&!propertyIsEnumerable.call(e,"callee")},isArray=Array.isArray,freeExports="object"==typeof exports&&exports&&!exports.nodeType&&exports,freeModule=freeExports&&"object"==typeof module&&module&&!module.nodeType&&module,moduleExports=freeModule&&freeModule.exports===freeExports,Buffer=moduleExports?root.Buffer:void 0,nativeIsBuffer=Buffer?Buffer.isBuffer:void 0,isBuffer=nativeIsBuffer||stubFalse,MAX_SAFE_INTEGER$1=9007199254740991,reIsUint=/^(?:0|[1-9]\d*)$/,argsTag$1="[object Arguments]",arrayTag="[object Array]",boolTag="[object Boolean]",dateTag="[object Date]",errorTag="[object Error]",funcTag$1="[object Function]",mapTag="[object Map]",numberTag="[object Number]",objectTag="[object Object]",regexpTag="[object RegExp]",setTag="[object Set]",stringTag="[object String]",weakMapTag="[object WeakMap]",arrayBufferTag="[object ArrayBuffer]",dataViewTag="[object DataView]",float32Tag="[object Float32Array]",float64Tag="[object Float64Array]",int8Tag="[object Int8Array]",int16Tag="[object Int16Array]",int32Tag="[object Int32Array]",uint8Tag="[object Uint8Array]",uint8ClampedTag="[object Uint8ClampedArray]",uint16Tag="[object Uint16Array]",uint32Tag="[object Uint32Array]",typedArrayTags={};typedArrayTags[float32Tag]=typedArrayTags[float64Tag]=typedArrayTags[int8Tag]=typedArrayTags[int16Tag]=typedArrayTags[int32Tag]=typedArrayTags[uint8Tag]=typedArrayTags[uint8ClampedTag]=typedArrayTags[uint16Tag]=typedArrayTags[uint32Tag]=!0,typedArrayTags[argsTag$1]=typedArrayTags[arrayTag]=typedArrayTags[arrayBufferTag]=typedArrayTags[boolTag]=typedArrayTags[dataViewTag]=typedArrayTags[dateTag]=typedArrayTags[errorTag]=typedArrayTags[funcTag$1]=typedArrayTags[mapTag]=typedArrayTags[numberTag]=typedArrayTags[objectTag]=typedArrayTags[regexpTag]=typedArrayTags[setTag]=typedArrayTags[stringTag]=typedArrayTags[weakMapTag]=!1;var freeExports$1="object"==typeof exports&&exports&&!exports.nodeType&&exports,freeModule$1=freeExports$1&&"object"==typeof module&&module&&!module.nodeType&&module,moduleExports$1=freeModule$1&&freeModule$1.exports===freeExports$1,freeProcess=moduleExports$1&&freeGlobal.process,nodeUtil=function(){try{return freeProcess&&freeProcess.binding("util")}catch(e){}}(),nodeIsTypedArray=nodeUtil&&nodeUtil.isTypedArray,isTypedArray=nodeIsTypedArray?baseUnary(nodeIsTypedArray):baseIsTypedArray,objectProto$2=Object.prototype,hasOwnProperty$1=objectProto$2.hasOwnProperty,objectProto$5=Object.prototype,nativeKeys=overArg(Object.keys,Object),objectProto$4=Object.prototype,hasOwnProperty$3=objectProto$4.hasOwnProperty,eachOfGeneric=doLimit(eachOfLimit,1/0),eachOf=function(e,t,r){var n=isArrayLike(e)?eachOfArrayLike:eachOfGeneric;n(e,wrapAsync$1(t),r)},map=doParallel(_asyncMap),applyEach=applyEach$1(map),mapLimit=doParallelLimit(_asyncMap),mapSeries=doLimit(mapLimit,1),applyEachSeries=applyEach$1(mapSeries),apply=function(e){var t=slice(arguments,1);return function(){var r=slice(arguments);return e.apply(null,t.concat(r))}},baseFor=createBaseFor(),auto=function(e,t,r){function n(e,t){g.push(function(){s(e,t)})}function i(){if(0===g.length&&0===y)return r(null,p);for(;g.length&&y2&&(n=slice(arguments,1)),t){var i={};baseForOwn(p,function(e,t){i[t]=e}),i[e]=n,m=!0,d=Object.create(null),r(t,i)}else p[e]=n,a(e)});y++;var i=wrapAsync$1(t[t.length-1]);t.length>1?i(p,n):i(n)}}function c(){for(var e,t=0;h.length;)e=h.pop(),t++,arrayEach(u(e),function(e){0===--b[e]&&h.push(e)});if(t!==f)throw new Error("async.auto cannot execute tasks due to a recursive dependency")}function u(t){var r=[];return baseForOwn(e,function(e,n){isArray(e)&&baseIndexOf(e,t,0)>=0&&r.push(n)}),r}"function"==typeof t&&(r=t,t=null),r=once(r||noop);var l=keys(e),f=l.length;if(!f)return r(null);t||(t=f);var p={},y=0,m=!1,d=Object.create(null),g=[],h=[],b={};baseForOwn(e,function(t,r){if(!isArray(t))return n(r,[t]),void h.push(r);var i=t.slice(0,t.length-1),a=i.length;return 0===a?(n(r,t),void h.push(r)):(b[r]=a,void arrayEach(i,function(s){if(!e[s])throw new Error("async.auto task `"+r+"` has a non-existent dependency `"+s+"` in "+i.join(", "));o(s,function(){a--,0===a&&n(r,t)})}))}),c(),i()},symbolTag="[object Symbol]",INFINITY=1/0,symbolProto=Symbol$1?Symbol$1.prototype:void 0,symbolToString=symbolProto?symbolProto.toString:void 0,rsAstralRange="\\ud800-\\udfff",rsComboMarksRange="\\u0300-\\u036f\\ufe20-\\ufe23",rsComboSymbolsRange="\\u20d0-\\u20f0",rsVarRange="\\ufe0e\\ufe0f",rsZWJ="\\u200d",reHasUnicode=RegExp("["+rsZWJ+rsAstralRange+rsComboMarksRange+rsComboSymbolsRange+rsVarRange+"]"),rsAstralRange$1="\\ud800-\\udfff",rsComboMarksRange$1="\\u0300-\\u036f\\ufe20-\\ufe23",rsComboSymbolsRange$1="\\u20d0-\\u20f0",rsVarRange$1="\\ufe0e\\ufe0f",rsAstral="["+rsAstralRange$1+"]",rsCombo="["+rsComboMarksRange$1+rsComboSymbolsRange$1+"]",rsFitz="\\ud83c[\\udffb-\\udfff]",rsModifier="(?:"+rsCombo+"|"+rsFitz+")",rsNonAstral="[^"+rsAstralRange$1+"]",rsRegional="(?:\\ud83c[\\udde6-\\uddff]){2}",rsSurrPair="[\\ud800-\\udbff][\\udc00-\\udfff]",rsZWJ$1="\\u200d",reOptMod=rsModifier+"?",rsOptVar="["+rsVarRange$1+"]?",rsOptJoin="(?:"+rsZWJ$1+"(?:"+[rsNonAstral,rsRegional,rsSurrPair].join("|")+")"+rsOptVar+reOptMod+")*",rsSeq=rsOptVar+reOptMod+rsOptJoin,rsSymbol="(?:"+[rsNonAstral+rsCombo+"?",rsCombo,rsRegional,rsSurrPair,rsAstral].join("|")+")",reUnicode=RegExp(rsFitz+"(?="+rsFitz+")|"+rsSymbol+rsSeq,"g"),reTrim=/^\s+|\s+$/g,FN_ARGS=/^(?:async\s+)?(function)?\s*[^\(]*\(\s*([^\)]*)\)/m,FN_ARG_SPLIT=/,/,FN_ARG=/(=.+)?(\s*)$/,STRIP_COMMENTS=/((\/\/.*$)|(\/\*[\s\S]*?\*\/))/gm,hasSetImmediate="function"==typeof setImmediate&&setImmediate,hasNextTick="object"==typeof process&&"function"==typeof process.nextTick,_defer;_defer=hasSetImmediate?setImmediate:hasNextTick?process.nextTick:fallback;var setImmediate$1=wrap(_defer);DLL.prototype.removeLink=function(e){return e.prev?e.prev.next=e.next:this.head=e.next,e.next?e.next.prev=e.prev:this.tail=e.prev,e.prev=e.next=null,this.length-=1,e},DLL.prototype.empty=DLL,DLL.prototype.insertAfter=function(e,t){t.prev=e,t.next=e.next,e.next?e.next.prev=t:this.tail=t,e.next=t,this.length+=1},DLL.prototype.insertBefore=function(e,t){t.prev=e.prev,t.next=e,e.prev?e.prev.next=t:this.head=t,e.prev=t,this.length+=1},DLL.prototype.unshift=function(e){this.head?this.insertBefore(this.head,e):setInitial(this,e)},DLL.prototype.push=function(e){this.tail?this.insertAfter(this.tail,e):setInitial(this,e)},DLL.prototype.shift=function(){return this.head&&this.removeLink(this.head)},DLL.prototype.pop=function(){return this.tail&&this.removeLink(this.tail)};var eachOfSeries=doLimit(eachOfLimit,1),compose=function(){return seq.apply(null,slice(arguments).reverse())},concat=doParallel(concat$1),concatSeries=doSeries(concat$1),constant=function(){var e=slice(arguments),t=[null].concat(e);return function(){var e=arguments[arguments.length-1];return e.apply(this,t)}},detect=doParallel(_createTester(identity,_findGetResult)),detectLimit=doParallelLimit(_createTester(identity,_findGetResult)),detectSeries=doLimit(detectLimit,1),dir=consoleFunc("dir"),eachSeries=doLimit(eachLimit$1,1),every=doParallel(_createTester(notId,notId)),everyLimit=doParallelLimit(_createTester(notId,notId)),everySeries=doLimit(everyLimit,1),filter=doParallel(_filter),filterLimit=doParallelLimit(_filter),filterSeries=doLimit(filterLimit,1),groupByLimit=function(e,t,r,n){n=n||noop;var i=wrapAsync$1(r);mapLimit(e,t,function(e,t){i(e,function(r,n){return r?t(r):t(null,{key:n,val:e})})},function(e,t){for(var r={},i=Object.prototype.hasOwnProperty,o=0;o=i.priority;)i=i.next;for(var o=0,a=e.length;o Date: Tue, 4 Apr 2017 12:27:28 -0400 Subject: linkify changelog --- CHANGELOG.md | 212 +++++++++++++++++++++++++++++------------------------------ 1 file changed, 106 insertions(+), 106 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fb1204b..89cba5c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,15 +1,15 @@ # v2.3.0 -- Added support for ES2017 `async` functions. Wherever you can pass a Node-style/CPS function that uses a callback, you can also pass an `async` function. Previously, you had to wrap `async` functions with `asyncify`. The caveat is that it will only work if `async` functions are supported natively in your environment, transpiled implementations can't be detected. (#1386, #1390) -- Small doc fix (#1392) +- Added support for ES2017 `async` functions. Wherever you can pass a Node-style/CPS function that uses a callback, you can also pass an `async` function. Previously, you had to wrap `async` functions with `asyncify`. The caveat is that it will only work if `async` functions are supported natively in your environment, transpiled implementations can't be detected. ([#1386](https://github.com/caolan/async/issues/1386), [#1390](https://github.com/caolan/async/issues/1390)) +- Small doc fix ([#1392](https://github.com/caolan/async/issues/1392)) # v2.2.0 -- Added `groupBy`, and the `Series`/`Limit` equivalents, analogous to [`_.groupBy`](http://lodash.com/docs#groupBy) (#1364) -- Fixed `transform` bug when `callback` was not passed (#1381) -- Added note about `reflect` to `parallel` docs (#1385) +- Added `groupBy`, and the `Series`/`Limit` equivalents, analogous to [`_.groupBy`](http://lodash.com/docs#groupBy) ([#1364](https://github.com/caolan/async/issues/1364)) +- Fixed `transform` bug when `callback` was not passed ([#1381](https://github.com/caolan/async/issues/1381)) +- Added note about `reflect` to `parallel` docs ([#1385](https://github.com/caolan/async/issues/1385)) # v2.1.5 -- Fix `auto` bug when function names collided with Array.prototype (#1358) -- Improve some error messages (#1349) +- Fix `auto` bug when function names collided with Array.prototype ([#1358](https://github.com/caolan/async/issues/1358)) +- Improve some error messages ([#1349](https://github.com/caolan/async/issues/1349)) - Avoid stack overflow case in queue - Fixed an issue in `some`, `every` and `find` where processing would continue after the result was determined. - Cleanup implementations of `some`, `every` and `find` @@ -19,19 +19,19 @@ - Create optimized hotpath for `filter` in array case. # v2.1.2 -- Fixed a stackoverflow bug with `detect`, `some`, `every` on large inputs (#1293). +- Fixed a stackoverflow bug with `detect`, `some`, `every` on large inputs ([#1293](https://github.com/caolan/async/issues/1293)). # v2.1.0 -- `retry` and `retryable` now support an optional `errorFilter` function that determines if the `task` should retry on the error (#1256, #1261) -- Optimized array iteration in `race`, `cargo`, `queue`, and `priorityQueue` (#1253) -- Added alias documentation to doc site (#1251, #1254) -- Added [BootStrap scrollspy](http://getbootstrap.com/javascript/#scrollspy) to docs to highlight in the sidebar the current method being viewed (#1289, #1300) -- Various minor doc fixes (#1263, #1264, #1271, #1278, #1280, #1282, #1302) +- `retry` and `retryable` now support an optional `errorFilter` function that determines if the `task` should retry on the error ([#1256](https://github.com/caolan/async/issues/1256), [#1261](https://github.com/caolan/async/issues/1261)) +- Optimized array iteration in `race`, `cargo`, `queue`, and `priorityQueue` ([#1253](https://github.com/caolan/async/issues/1253)) +- Added alias documentation to doc site ([#1251](https://github.com/caolan/async/issues/1251), [#1254](https://github.com/caolan/async/issues/1254)) +- Added [BootStrap scrollspy](http://getbootstrap.com/javascript/#scrollspy) to docs to highlight in the sidebar the current method being viewed ([#1289](https://github.com/caolan/async/issues/1289), [#1300](https://github.com/caolan/async/issues/1300)) +- Various minor doc fixes ([#1263](https://github.com/caolan/async/issues/1263), [#1264](https://github.com/caolan/async/issues/1264), [#1271](https://github.com/caolan/async/issues/1271), [#1278](https://github.com/caolan/async/issues/1278), [#1280](https://github.com/caolan/async/issues/1280), [#1282](https://github.com/caolan/async/issues/1282), [#1302](https://github.com/caolan/async/issues/1302)) # v2.0.1 -- Significantly optimized all iteration based collection methods such as `each`, `map`, `filter`, etc (#1245, #1246, #1247). +- Significantly optimized all iteration based collection methods such as `each`, `map`, `filter`, etc ([#1245](https://github.com/caolan/async/issues/1245), [#1246](https://github.com/caolan/async/issues/1246), [#1247](https://github.com/caolan/async/issues/1247)). # v2.0.0 @@ -62,96 +62,96 @@ Another big performance win has been re-implementing `queue`, `cargo`, and `prio ## New Features -- Async is now modularized. Individual functions can be `require()`d from the main package. (`require('async/auto')`) (#984, #996) -- Async is also available as a collection of ES2015 modules in the new `async-es` package. (`import {forEachSeries} from 'async-es'`) (#984, #996) -- Added `race`, analogous to `Promise.race()`. It will run an array of async tasks in parallel and will call its callback with the result of the first task to respond. (#568, #1038) -- Collection methods now accept ES2015 iterators. Maps, Sets, and anything that implements the iterator spec can now be passed directly to `each`, `map`, `parallel`, etc.. (#579, #839, #1074) -- Added `mapValues`, for mapping over the properties of an object and returning an object with the same keys. (#1157, #1177) -- Added `timeout`, a wrapper for an async function that will make the task time-out after the specified time. (#1007, #1027) -- Added `reflect` and `reflectAll`, analagous to [`Promise.reflect()`](http://bluebirdjs.com/docs/api/reflect.html), a wrapper for async tasks that always succeeds, by gathering results and errors into an object. (#942, #1012, #1095) -- `constant` supports dynamic arguments -- it will now always use its last argument as the callback. (#1016, #1052) -- `setImmediate` and `nextTick` now support arguments to partially apply to the deferred function, like the node-native versions do. (#940, #1053) -- `auto` now supports resolving cyclic dependencies using [Kahn's algorithm](https://en.wikipedia.org/wiki/Topological_sorting#Kahn.27s_algorithm) (#1140). -- Added `autoInject`, a relative of `auto` that automatically spreads a task's dependencies as arguments to the task function. (#608, #1055, #1099, #1100) -- You can now limit the concurrency of `auto` tasks. (#635, #637) -- Added `retryable`, a relative of `retry` that wraps an async function, making it retry when called. (#1058) -- `retry` now supports specifying a function that determines the next time interval, useful for exponential backoff, logging and other retry strategies. (#1161) -- `retry` will now pass all of the arguments the task function was resolved with to the callback (#1231). -- Added `q.unsaturated` -- callback called when a `queue`'s number of running workers falls below a threshold. (#868, #1030, #1033, #1034) -- Added `q.error` -- a callback called whenever a `queue` task calls its callback with an error. (#1170) -- `applyEach` and `applyEachSeries` now pass results to the final callback. (#1088) +- Async is now modularized. Individual functions can be `require()`d from the main package. (`require('async/auto')`) ([#984](https://github.com/caolan/async/issues/984), [#996](https://github.com/caolan/async/issues/996)) +- Async is also available as a collection of ES2015 modules in the new `async-es` package. (`import {forEachSeries} from 'async-es'`) ([#984](https://github.com/caolan/async/issues/984), [#996](https://github.com/caolan/async/issues/996)) +- Added `race`, analogous to `Promise.race()`. It will run an array of async tasks in parallel and will call its callback with the result of the first task to respond. ([#568](https://github.com/caolan/async/issues/568), [#1038](https://github.com/caolan/async/issues/1038)) +- Collection methods now accept ES2015 iterators. Maps, Sets, and anything that implements the iterator spec can now be passed directly to `each`, `map`, `parallel`, etc.. ([#579](https://github.com/caolan/async/issues/579), [#839](https://github.com/caolan/async/issues/839), [#1074](https://github.com/caolan/async/issues/1074)) +- Added `mapValues`, for mapping over the properties of an object and returning an object with the same keys. ([#1157](https://github.com/caolan/async/issues/1157), [#1177](https://github.com/caolan/async/issues/1177)) +- Added `timeout`, a wrapper for an async function that will make the task time-out after the specified time. ([#1007](https://github.com/caolan/async/issues/1007), [#1027](https://github.com/caolan/async/issues/1027)) +- Added `reflect` and `reflectAll`, analagous to [`Promise.reflect()`](http://bluebirdjs.com/docs/api/reflect.html), a wrapper for async tasks that always succeeds, by gathering results and errors into an object. ([#942](https://github.com/caolan/async/issues/942), [#1012](https://github.com/caolan/async/issues/1012), [#1095](https://github.com/caolan/async/issues/1095)) +- `constant` supports dynamic arguments -- it will now always use its last argument as the callback. ([#1016](https://github.com/caolan/async/issues/1016), [#1052](https://github.com/caolan/async/issues/1052)) +- `setImmediate` and `nextTick` now support arguments to partially apply to the deferred function, like the node-native versions do. ([#940](https://github.com/caolan/async/issues/940), [#1053](https://github.com/caolan/async/issues/1053)) +- `auto` now supports resolving cyclic dependencies using [Kahn's algorithm](https://en.wikipedia.org/wiki/Topological_sorting#Kahn.27s_algorithm) ([#1140](https://github.com/caolan/async/issues/1140)). +- Added `autoInject`, a relative of `auto` that automatically spreads a task's dependencies as arguments to the task function. ([#608](https://github.com/caolan/async/issues/608), [#1055](https://github.com/caolan/async/issues/1055), [#1099](https://github.com/caolan/async/issues/1099), [#1100](https://github.com/caolan/async/issues/1100)) +- You can now limit the concurrency of `auto` tasks. ([#635](https://github.com/caolan/async/issues/635), [#637](https://github.com/caolan/async/issues/637)) +- Added `retryable`, a relative of `retry` that wraps an async function, making it retry when called. ([#1058](https://github.com/caolan/async/issues/1058)) +- `retry` now supports specifying a function that determines the next time interval, useful for exponential backoff, logging and other retry strategies. ([#1161](https://github.com/caolan/async/issues/1161)) +- `retry` will now pass all of the arguments the task function was resolved with to the callback ([#1231](https://github.com/caolan/async/issues/1231)). +- Added `q.unsaturated` -- callback called when a `queue`'s number of running workers falls below a threshold. ([#868](https://github.com/caolan/async/issues/868), [#1030](https://github.com/caolan/async/issues/1030), [#1033](https://github.com/caolan/async/issues/1033), [#1034](https://github.com/caolan/async/issues/1034)) +- Added `q.error` -- a callback called whenever a `queue` task calls its callback with an error. ([#1170](https://github.com/caolan/async/issues/1170)) +- `applyEach` and `applyEachSeries` now pass results to the final callback. ([#1088](https://github.com/caolan/async/issues/1088)) ## Breaking changes -- Calling a callback more than once is considered an error, and an error will be thrown. This had an explicit breaking change in `waterfall`. If you were relying on this behavior, you should more accurately represent your control flow as an event emitter or stream. (#814, #815, #1048, #1050) -- `auto` task functions now always take the callback as the last argument. If a task has dependencies, the `results` object will be passed as the first argument. To migrate old task functions, wrap them with [`_.flip`](https://lodash.com/docs#flip) (#1036, #1042) -- Internal `setImmediate` calls have been refactored away. This may make existing flows vulnerable to stack overflows if you use many synchronous functions in series. Use `ensureAsync` to work around this. (#696, #704, #1049, #1050) -- `map` used to return an object when iterating over an object. `map` now always returns an array, like in other libraries. The previous object behavior has been split out into `mapValues`. (#1157, #1177) -- `filter`, `reject`, `some`, `every`, and related functions now expect an error as the first callback argument, rather than just a simple boolean. Pass `null` as the first argument, or use `fs.access` instead of `fs.exists`. (#118, #774, #1028, #1041) -- `{METHOD}` and `{METHOD}Series` are now implemented in terms of `{METHOD}Limit`. This is a major internal simplification, and is not expected to cause many problems, but it does subtly affect how functions execute internally. (#778, #847) -- `retry`'s callback is now optional. Previously, omitting the callback would partially apply the function, meaning it could be passed directly as a task to `series` or `auto`. The partially applied "control-flow" behavior has been separated out into `retryable`. (#1054, #1058) -- The test function for `whilst`, `until`, and `during` used to be passed non-error args from the iteratee function's callback, but this led to weirdness where the first call of the test function would be passed no args. We have made it so the test function is never passed extra arguments, and only the `doWhilst`, `doUntil`, and `doDuring` functions pass iteratee callback arguments to the test function (#1217, #1224) -- The `q.tasks` array has been renamed `q._tasks` and is now implemented as a doubly linked list (DLL). Any code that used to interact with this array will need to be updated to either use the provided helpers or support DLLs (#1205). -- The timing of the `q.saturated()` callback in a `queue` has been modified to better reflect when tasks pushed to the queue will start queueing. (#724, #1078) -- Removed `iterator` method in favour of [ES2015 iterator protocol](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Iterators_and_Generators ) which natively supports arrays (#1237) -- Dropped support for Component, Jam, SPM, and Volo (#1175, ##176) +- Calling a callback more than once is considered an error, and an error will be thrown. This had an explicit breaking change in `waterfall`. If you were relying on this behavior, you should more accurately represent your control flow as an event emitter or stream. ([#814](https://github.com/caolan/async/issues/814), [#815](https://github.com/caolan/async/issues/815), [#1048](https://github.com/caolan/async/issues/1048), [#1050](https://github.com/caolan/async/issues/1050)) +- `auto` task functions now always take the callback as the last argument. If a task has dependencies, the `results` object will be passed as the first argument. To migrate old task functions, wrap them with [`_.flip`](https://lodash.com/docs#flip) ([#1036](https://github.com/caolan/async/issues/1036), [#1042](https://github.com/caolan/async/issues/1042)) +- Internal `setImmediate` calls have been refactored away. This may make existing flows vulnerable to stack overflows if you use many synchronous functions in series. Use `ensureAsync` to work around this. ([#696](https://github.com/caolan/async/issues/696), [#704](https://github.com/caolan/async/issues/704), [#1049](https://github.com/caolan/async/issues/1049), [#1050](https://github.com/caolan/async/issues/1050)) +- `map` used to return an object when iterating over an object. `map` now always returns an array, like in other libraries. The previous object behavior has been split out into `mapValues`. ([#1157](https://github.com/caolan/async/issues/1157), [#1177](https://github.com/caolan/async/issues/1177)) +- `filter`, `reject`, `some`, `every`, and related functions now expect an error as the first callback argument, rather than just a simple boolean. Pass `null` as the first argument, or use `fs.access` instead of `fs.exists`. ([#118](https://github.com/caolan/async/issues/118), [#774](https://github.com/caolan/async/issues/774), [#1028](https://github.com/caolan/async/issues/1028), [#1041](https://github.com/caolan/async/issues/1041)) +- `{METHOD}` and `{METHOD}Series` are now implemented in terms of `{METHOD}Limit`. This is a major internal simplification, and is not expected to cause many problems, but it does subtly affect how functions execute internally. ([#778](https://github.com/caolan/async/issues/778), [#847](https://github.com/caolan/async/issues/847)) +- `retry`'s callback is now optional. Previously, omitting the callback would partially apply the function, meaning it could be passed directly as a task to `series` or `auto`. The partially applied "control-flow" behavior has been separated out into `retryable`. ([#1054](https://github.com/caolan/async/issues/1054), [#1058](https://github.com/caolan/async/issues/1058)) +- The test function for `whilst`, `until`, and `during` used to be passed non-error args from the iteratee function's callback, but this led to weirdness where the first call of the test function would be passed no args. We have made it so the test function is never passed extra arguments, and only the `doWhilst`, `doUntil`, and `doDuring` functions pass iteratee callback arguments to the test function ([#1217](https://github.com/caolan/async/issues/1217), [#1224](https://github.com/caolan/async/issues/1224)) +- The `q.tasks` array has been renamed `q._tasks` and is now implemented as a doubly linked list (DLL). Any code that used to interact with this array will need to be updated to either use the provided helpers or support DLLs ([#1205](https://github.com/caolan/async/issues/1205)). +- The timing of the `q.saturated()` callback in a `queue` has been modified to better reflect when tasks pushed to the queue will start queueing. ([#724](https://github.com/caolan/async/issues/724), [#1078](https://github.com/caolan/async/issues/1078)) +- Removed `iterator` method in favour of [ES2015 iterator protocol](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Iterators_and_Generators ) which natively supports arrays ([#1237](https://github.com/caolan/async/issues/1237)) +- Dropped support for Component, Jam, SPM, and Volo ([#1175](https://github.com/caolan/async/issues/1175), #[#176](https://github.com/caolan/async/issues/176)) ## Bug Fixes -- Improved handling of no dependency cases in `auto` & `autoInject` (#1147). -- Fixed a bug where the callback generated by `asyncify` with `Promises` could resolve twice (#1197). -- Fixed several documented optional callbacks not actually being optional (#1223). +- Improved handling of no dependency cases in `auto` & `autoInject` ([#1147](https://github.com/caolan/async/issues/1147)). +- Fixed a bug where the callback generated by `asyncify` with `Promises` could resolve twice ([#1197](https://github.com/caolan/async/issues/1197)). +- Fixed several documented optional callbacks not actually being optional ([#1223](https://github.com/caolan/async/issues/1223)). ## Other - Added `someSeries` and `everySeries` for symmetry, as well as a complete set of `any`/`anyLimit`/`anySeries` and `all`/`/allLmit`/`allSeries` aliases. - Added `find` as an alias for `detect. (as well as `findLimit` and `findSeries`). -- Various doc fixes (#1005, #1008, #1010, #1015, #1021, #1037, #1039, #1051, #1102, #1107, #1121, #1123, #1129, #1135, #1138, #1141, #1153, #1216, #1217, #1232, #1233, #1236, #1238) +- Various doc fixes ([#1005](https://github.com/caolan/async/issues/1005), [#1008](https://github.com/caolan/async/issues/1008), [#1010](https://github.com/caolan/async/issues/1010), [#1015](https://github.com/caolan/async/issues/1015), [#1021](https://github.com/caolan/async/issues/1021), [#1037](https://github.com/caolan/async/issues/1037), [#1039](https://github.com/caolan/async/issues/1039), [#1051](https://github.com/caolan/async/issues/1051), [#1102](https://github.com/caolan/async/issues/1102), [#1107](https://github.com/caolan/async/issues/1107), [#1121](https://github.com/caolan/async/issues/1121), [#1123](https://github.com/caolan/async/issues/1123), [#1129](https://github.com/caolan/async/issues/1129), [#1135](https://github.com/caolan/async/issues/1135), [#1138](https://github.com/caolan/async/issues/1138), [#1141](https://github.com/caolan/async/issues/1141), [#1153](https://github.com/caolan/async/issues/1153), [#1216](https://github.com/caolan/async/issues/1216), [#1217](https://github.com/caolan/async/issues/1217), [#1232](https://github.com/caolan/async/issues/1232), [#1233](https://github.com/caolan/async/issues/1233), [#1236](https://github.com/caolan/async/issues/1236), [#1238](https://github.com/caolan/async/issues/1238)) Thank you [**@aearly**](github.com/aearly) and [**@megawac**](github.com/megawac) for taking the lead on version 2 of async. ------------------------------------------ # v1.5.2 -- Allow using `"constructor"` as an argument in `memoize` (#998) -- Give a better error messsage when `auto` dependency checking fails (#994) -- Various doc updates (#936, #956, #979, #1002) +- Allow using `"constructor"` as an argument in `memoize` ([#998](https://github.com/caolan/async/issues/998)) +- Give a better error messsage when `auto` dependency checking fails ([#994](https://github.com/caolan/async/issues/994)) +- Various doc updates ([#936](https://github.com/caolan/async/issues/936), [#956](https://github.com/caolan/async/issues/956), [#979](https://github.com/caolan/async/issues/979), [#1002](https://github.com/caolan/async/issues/1002)) # v1.5.1 -- Fix issue with `pause` in `queue` with concurrency enabled (#946) -- `while` and `until` now pass the final result to callback (#963) -- `auto` will properly handle concurrency when there is no callback (#966) -- `auto` will no. properly stop execution when an error occurs (#988, #993) -- Various doc fixes (#971, #980) +- Fix issue with `pause` in `queue` with concurrency enabled ([#946](https://github.com/caolan/async/issues/946)) +- `while` and `until` now pass the final result to callback ([#963](https://github.com/caolan/async/issues/963)) +- `auto` will properly handle concurrency when there is no callback ([#966](https://github.com/caolan/async/issues/966)) +- `auto` will no. properly stop execution when an error occurs ([#988](https://github.com/caolan/async/issues/988), [#993](https://github.com/caolan/async/issues/993)) +- Various doc fixes ([#971](https://github.com/caolan/async/issues/971), [#980](https://github.com/caolan/async/issues/980)) # v1.5.0 -- Added `transform`, analogous to [`_.transform`](http://lodash.com/docs#transform) (#892) -- `map` now returns an object when an object is passed in, rather than array with non-numeric keys. `map` will begin always returning an array with numeric indexes in the next major release. (#873) -- `auto` now accepts an optional `concurrency` argument to limit the number o. running tasks (#637) -- Added `queue#workersList()`, to retrieve the lis. of currently running tasks. (#891) -- Various code simplifications (#896, #904) -- Various doc fixes :scroll: (#890, #894, #903, #905, #912) +- Added `transform`, analogous to [`_.transform`](http://lodash.com/docs#transform) ([#892](https://github.com/caolan/async/issues/892)) +- `map` now returns an object when an object is passed in, rather than array with non-numeric keys. `map` will begin always returning an array with numeric indexes in the next major release. ([#873](https://github.com/caolan/async/issues/873)) +- `auto` now accepts an optional `concurrency` argument to limit the number o. running tasks ([#637](https://github.com/caolan/async/issues/637)) +- Added `queue#workersList()`, to retrieve the lis. of currently running tasks. ([#891](https://github.com/caolan/async/issues/891)) +- Various code simplifications ([#896](https://github.com/caolan/async/issues/896), [#904](https://github.com/caolan/async/issues/904)) +- Various doc fixes :scroll: ([#890](https://github.com/caolan/async/issues/890), [#894](https://github.com/caolan/async/issues/894), [#903](https://github.com/caolan/async/issues/903), [#905](https://github.com/caolan/async/issues/905), [#912](https://github.com/caolan/async/issues/912)) # v1.4.2 -- Ensure coverage files don't get published on npm (#879) +- Ensure coverage files don't get published on npm ([#879](https://github.com/caolan/async/issues/879)) # v1.4.1 -- Add in overlooked `detectLimit` method (#866) -- Removed unnecessary files from npm releases (#861) -- Removed usage of a reserved word to prevent :boom: in older environments (#870) +- Add in overlooked `detectLimit` method ([#866](https://github.com/caolan/async/issues/866)) +- Removed unnecessary files from npm releases ([#861](https://github.com/caolan/async/issues/861)) +- Removed usage of a reserved word to prevent :boom: in older environments ([#870](https://github.com/caolan/async/issues/870)) # v1.4.0 -- `asyncify` now supports promises (#840) -- Added `Limit` versions of `filter` and `reject` (#836) -- Add `Limit` versions of `detect`, `some` and `every` (#828, #829) -- `some`, `every` and `detect` now short circuit early (#828, #829) -- Improve detection of the global object (#804), enabling use in WebWorkers -- `whilst` now called with arguments from iterator (#823) -- `during` now gets called with arguments from iterator (#824) +- `asyncify` now supports promises ([#840](https://github.com/caolan/async/issues/840)) +- Added `Limit` versions of `filter` and `reject` ([#836](https://github.com/caolan/async/issues/836)) +- Add `Limit` versions of `detect`, `some` and `every` ([#828](https://github.com/caolan/async/issues/828), [#829](https://github.com/caolan/async/issues/829)) +- `some`, `every` and `detect` now short circuit early ([#828](https://github.com/caolan/async/issues/828), [#829](https://github.com/caolan/async/issues/829)) +- Improve detection of the global object ([#804](https://github.com/caolan/async/issues/804)), enabling use in WebWorkers +- `whilst` now called with arguments from iterator ([#823](https://github.com/caolan/async/issues/823)) +- `during` now gets called with arguments from iterator ([#824](https://github.com/caolan/async/issues/824)) - Code simplifications and optimizations aplenty ([diff](https://github.com/caolan/async/compare/v1.3.0...v1.4.0)) @@ -159,42 +159,42 @@ Thank you [**@aearly**](github.com/aearly) and [**@megawac**](github.com/megawac New Features: - Added `constant` -- Added `asyncify`/`wrapSync` for making sync functions work with callbacks. (#671, #806) -- Added `during` and `doDuring`, which are like `whilst` with an async truth test. (#800) -- `retry` now accepts an `interval` parameter to specify a delay between retries. (#793) -- `async` should work better in Web Workers due to better `root` detection (#804) -- Callbacks are now optional in `whilst`, `doWhilst`, `until`, and `doUntil` (#642) -- Various internal updates (#786, #801, #802, #803) -- Various doc fixes (#790, #794) +- Added `asyncify`/`wrapSync` for making sync functions work with callbacks. ([#671](https://github.com/caolan/async/issues/671), [#806](https://github.com/caolan/async/issues/806)) +- Added `during` and `doDuring`, which are like `whilst` with an async truth test. ([#800](https://github.com/caolan/async/issues/800)) +- `retry` now accepts an `interval` parameter to specify a delay between retries. ([#793](https://github.com/caolan/async/issues/793)) +- `async` should work better in Web Workers due to better `root` detection ([#804](https://github.com/caolan/async/issues/804)) +- Callbacks are now optional in `whilst`, `doWhilst`, `until`, and `doUntil` ([#642](https://github.com/caolan/async/issues/642)) +- Various internal updates ([#786](https://github.com/caolan/async/issues/786), [#801](https://github.com/caolan/async/issues/801), [#802](https://github.com/caolan/async/issues/802), [#803](https://github.com/caolan/async/issues/803)) +- Various doc fixes ([#790](https://github.com/caolan/async/issues/790), [#794](https://github.com/caolan/async/issues/794)) Bug Fixes: -- `cargo` now exposes the `payload` size, and `cargo.payload` can be changed on the fly after the `cargo` is created. (#740, #744, #783) +- `cargo` now exposes the `payload` size, and `cargo.payload` can be changed on the fly after the `cargo` is created. ([#740](https://github.com/caolan/async/issues/740), [#744](https://github.com/caolan/async/issues/744), [#783](https://github.com/caolan/async/issues/783)) # v1.2.1 Bug Fix: -- Small regression with synchronous iterator behavior in `eachSeries` with a 1-element array. Before 1.1.0, `eachSeries`'s callback was called on the same tick, which this patch restores. In 2.0.0, it will be called on the next tick. (#782) +- Small regression with synchronous iterator behavior in `eachSeries` with a 1-element array. Before 1.1.0, `eachSeries`'s callback was called on the same tick, which this patch restores. In 2.0.0, it will be called on the next tick. ([#782](https://github.com/caolan/async/issues/782)) # v1.2.0 New Features: -- Added `timesLimit` (#743) -- `concurrency` can be changed after initialization in `queue` by setting `q.concurrency`. The new concurrency will be reflected the next time a task is processed. (#747, #772) +- Added `timesLimit` ([#743](https://github.com/caolan/async/issues/743)) +- `concurrency` can be changed after initialization in `queue` by setting `q.concurrency`. The new concurrency will be reflected the next time a task is processed. ([#747](https://github.com/caolan/async/issues/747), [#772](https://github.com/caolan/async/issues/772)) Bug Fixes: -- Fixed a regression in `each` and family with empty arrays that have additional properties. (#775, #777) +- Fixed a regression in `each` and family with empty arrays that have additional properties. ([#775](https://github.com/caolan/async/issues/775), [#777](https://github.com/caolan/async/issues/777)) # v1.1.1 Bug Fix: -- Small regression with synchronous iterator behavior in `eachSeries` with a 1-element array. Before 1.1.0, `eachSeries`'s callback was called on the same tick, which this patch restores. In 2.0.0, it will be called on the next tick. (#782) +- Small regression with synchronous iterator behavior in `eachSeries` with a 1-element array. Before 1.1.0, `eachSeries`'s callback was called on the same tick, which this patch restores. In 2.0.0, it will be called on the next tick. ([#782](https://github.com/caolan/async/issues/782)) # v1.1.0 @@ -202,23 +202,23 @@ Bug Fix: New Features: - `cargo` now supports all of the same methods and event callbacks as `queue`. -- Added `ensureAsync` - A wrapper that ensures an async function calls its callback on a later tick. (#769) +- Added `ensureAsync` - A wrapper that ensures an async function calls its callback on a later tick. ([#769](https://github.com/caolan/async/issues/769)) - Optimized `map`, `eachOf`, and `waterfall` families of functions -- Passing a `null` or `undefined` array to `map`, `each`, `parallel` and families will be treated as an empty array (#667). -- The callback is now optional for the composed results of `compose` and `seq`. (#618) +- Passing a `null` or `undefined` array to `map`, `each`, `parallel` and families will be treated as an empty array ([#667](https://github.com/caolan/async/issues/667)). +- The callback is now optional for the composed results of `compose` and `seq`. ([#618](https://github.com/caolan/async/issues/618)) - Reduced file size by 4kb, (minified version by 1kb) -- Added code coverage through `nyc` and `coveralls` (#768) +- Added code coverage through `nyc` and `coveralls` ([#768](https://github.com/caolan/async/issues/768)) Bug Fixes: -- `forever` will no longer stack overflow with a synchronous iterator (#622) -- `eachLimit` and other limit functions will stop iterating once an error occurs (#754) -- Always pass `null` in callbacks when there is no error (#439) -- Ensure proper conditions when calling `drain()` after pushing an empty data set to a queue (#668) -- `each` and family will properly handle an empty array (#578) -- `eachSeries` and family will finish if the underlying array is modified during execution (#557) -- `queue` will throw if a non-function is passed to `q.push()` (#593) -- Doc fixes (#629, #766) +- `forever` will no longer stack overflow with a synchronous iterator ([#622](https://github.com/caolan/async/issues/622)) +- `eachLimit` and other limit functions will stop iterating once an error occurs ([#754](https://github.com/caolan/async/issues/754)) +- Always pass `null` in callbacks when there is no error ([#439](https://github.com/caolan/async/issues/439)) +- Ensure proper conditions when calling `drain()` after pushing an empty data set to a queue ([#668](https://github.com/caolan/async/issues/668)) +- `each` and family will properly handle an empty array ([#578](https://github.com/caolan/async/issues/578)) +- `eachSeries` and family will finish if the underlying array is modified during execution ([#557](https://github.com/caolan/async/issues/557)) +- `queue` will throw if a non-function is passed to `q.push()` ([#593](https://github.com/caolan/async/issues/593)) +- Doc fixes ([#629](https://github.com/caolan/async/issues/629), [#766](https://github.com/caolan/async/issues/766)) # v1.0.0 @@ -228,12 +228,12 @@ No known breaking changes, we are simply complying with semver from here on out. Changes: - Start using a changelog! -- Add `forEachOf` for iterating over Objects (or to iterate Arrays with indexes available) (#168 #704 #321) -- Detect deadlocks in `auto` (#663) -- Better support for require.js (#527) -- Throw if queue created with concurrency `0` (#714) -- Fix unneeded iteration in `queue.resume()` (#758) -- Guard against timer mocking overriding `setImmediate` (#609 #611) -- Miscellaneous doc fixes (#542 #596 #615 #628 #631 #690 #729) -- Use single noop function internally (#546) +- Add `forEachOf` for iterating over Objects (or to iterate Arrays with indexes available) ([#168](https://github.com/caolan/async/issues/168) [#704](https://github.com/caolan/async/issues/704) [#321](https://github.com/caolan/async/issues/321)) +- Detect deadlocks in `auto` ([#663](https://github.com/caolan/async/issues/663)) +- Better support for require.js ([#527](https://github.com/caolan/async/issues/527)) +- Throw if queue created with concurrency `0` ([#714](https://github.com/caolan/async/issues/714)) +- Fix unneeded iteration in `queue.resume()` ([#758](https://github.com/caolan/async/issues/758)) +- Guard against timer mocking overriding `setImmediate` ([#609](https://github.com/caolan/async/issues/609) [#611](https://github.com/caolan/async/issues/611)) +- Miscellaneous doc fixes ([#542](https://github.com/caolan/async/issues/542) [#596](https://github.com/caolan/async/issues/596) [#615](https://github.com/caolan/async/issues/615) [#628](https://github.com/caolan/async/issues/628) [#631](https://github.com/caolan/async/issues/631) [#690](https://github.com/caolan/async/issues/690) [#729](https://github.com/caolan/async/issues/729)) +- Use single noop function internally ([#546](https://github.com/caolan/async/issues/546)) - Optimize internal `_each`, `_map` and `_keys` functions. -- cgit v1.2.1 From c08f87832027f7100f0d0a97593daf53edc00b7a Mon Sep 17 00:00:00 2001 From: Graeme Yeates Date: Tue, 4 Apr 2017 12:31:51 -0400 Subject: Add changelog to nav --- support/jsdoc/theme/tmpl/layout.tmpl | 1 + 1 file changed, 1 insertion(+) diff --git a/support/jsdoc/theme/tmpl/layout.tmpl b/support/jsdoc/theme/tmpl/layout.tmpl index 631efa4..a5a3421 100644 --- a/support/jsdoc/theme/tmpl/layout.tmpl +++ b/support/jsdoc/theme/tmpl/layout.tmpl @@ -41,6 +41,7 @@
  • Home
  • Docs
  • +
  • Changelog