summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Early <alexander.early@gmail.com>2018-09-30 17:00:10 -0700
committerGitHub <noreply@github.com>2018-09-30 17:00:10 -0700
commit8aecf108b3922bc5211036706a0f6f75e02bd42b (patch)
tree0f7b6bee315231ef4aefdfbee154822921de231f
parentdf41256f49c9bb3126e035c95aca7860329b6acf (diff)
downloadasync-8aecf108b3922bc5211036706a0f6f75e02bd42b.tar.gz
feat: await-able Async methods (#1572)
* make each and family awaitable * dont pretend they're AsyncFunctions * check errors * ensure function name is preserved somehow * awaitable concat * awaitable detect * awaitable every/filter * awaitable groupBy * awaitable map/mapValues * awaitable reduce * awaitable reject * awaitable some * awaitable transform * awaitable times * awaitable auto * awaitable compose/seq * awaitable whilst/until (lol) * awaitable forever * awaitable parallel/race * awaitable retry * awaitable series (lol) * awaitable tryEach * awaitable waterfall (lol) * lint * cleanup, remove noop and unused internal functions
-rw-r--r--lib/auto.js13
-rw-r--r--lib/autoInject.js3
-rw-r--r--lib/compose.js5
-rw-r--r--lib/concat.js10
-rw-r--r--lib/concatLimit.js9
-rw-r--r--lib/concatSeries.js10
-rw-r--r--lib/detect.js9
-rw-r--r--lib/detectLimit.js9
-rw-r--r--lib/detectSeries.js12
-rw-r--r--lib/doUntil.js3
-rw-r--r--lib/doWhilst.js11
-rw-r--r--lib/each.js8
-rw-r--r--lib/eachLimit.js7
-rw-r--r--lib/eachOf.js16
-rw-r--r--lib/eachOfLimit.js8
-rw-r--r--lib/eachOfSeries.js8
-rw-r--r--lib/eachSeries.js8
-rw-r--r--lib/every.js9
-rw-r--r--lib/everyLimit.js9
-rw-r--r--lib/everySeries.js11
-rw-r--r--lib/filter.js11
-rw-r--r--lib/filterLimit.js11
-rw-r--r--lib/filterSeries.js11
-rw-r--r--lib/forever.js11
-rw-r--r--lib/groupBy.js6
-rw-r--r--lib/groupByLimit.js11
-rw-r--r--lib/groupBySeries.js7
-rw-r--r--lib/internal/awaitify.js24
-rw-r--r--lib/internal/createTester.js6
-rw-r--r--lib/internal/doLimit.js3
-rw-r--r--lib/internal/doParallel.js6
-rw-r--r--lib/internal/doParallelLimit.js6
-rw-r--r--lib/internal/eachOfLimit.js3
-rw-r--r--lib/internal/filter.js3
-rw-r--r--lib/internal/initialParams.js2
-rw-r--r--lib/internal/map.js2
-rw-r--r--lib/internal/noop.js1
-rw-r--r--lib/internal/once.js6
-rw-r--r--lib/internal/parallel.js7
-rw-r--r--lib/internal/promiseCallback.js19
-rw-r--r--lib/internal/queue.js3
-rw-r--r--lib/internal/reject.js4
-rw-r--r--lib/internal/wrapAsync.js1
-rw-r--r--lib/map.js11
-rw-r--r--lib/mapLimit.js11
-rw-r--r--lib/mapSeries.js11
-rw-r--r--lib/mapValues.js8
-rw-r--r--lib/mapValuesLimit.js14
-rw-r--r--lib/mapValuesSeries.js6
-rw-r--r--lib/parallel.js7
-rw-r--r--lib/parallelLimit.js3
-rw-r--r--lib/priorityQueue.js7
-rw-r--r--lib/race.js8
-rw-r--r--lib/reduce.js11
-rw-r--r--lib/reduceRight.js3
-rw-r--r--lib/reject.js11
-rw-r--r--lib/rejectLimit.js12
-rw-r--r--lib/rejectSeries.js11
-rw-r--r--lib/retry.js8
-rw-r--r--lib/retryable.js17
-rw-r--r--lib/seq.js6
-rw-r--r--lib/series.js5
-rw-r--r--lib/some.js9
-rw-r--r--lib/someLimit.js9
-rw-r--r--lib/someSeries.js11
-rw-r--r--lib/sortBy.js7
-rw-r--r--lib/times.js6
-rw-r--r--lib/timesLimit.js5
-rw-r--r--lib/timesSeries.js6
-rw-r--r--lib/transform.js8
-rw-r--r--lib/tryEach.js10
-rw-r--r--lib/until.js3
-rw-r--r--lib/waterfall.js8
-rw-r--r--lib/whilst.js10
-rw-r--r--test/asyncFunctions.js3
-rw-r--r--test/es2017/awaitableFunctions.js579
-rw-r--r--test/retry.js2
77 files changed, 987 insertions, 201 deletions
diff --git a/lib/auto.js b/lib/auto.js
index b06e3c5..ad92d74 100644
--- a/lib/auto.js
+++ b/lib/auto.js
@@ -1,8 +1,7 @@
-import noop from './internal/noop';
-
import once from './internal/once';
import onlyOnce from './internal/onlyOnce';
import wrapAsync from './internal/wrapAsync';
+import { promiseCallback, PROMISE_SYMBOL } from './internal/promiseCallback'
/**
* Determines the best order for running the {@link AsyncFunction}s in `tasks`, based on
@@ -42,7 +41,7 @@ import wrapAsync from './internal/wrapAsync';
* pass an error to their callback. Results are always returned; however, if an
* error occurs, no further `tasks` will be performed, and the results object
* will only contain partial results. Invoked with (err, results).
- * @returns undefined
+ * @returns {Promise} a promise, if a callback is not passed
* @example
*
* async.auto({
@@ -83,13 +82,13 @@ import wrapAsync from './internal/wrapAsync';
* console.log('results = ', results);
* });
*/
-export default function (tasks, concurrency, callback) {
- if (typeof concurrency === 'function') {
+export default function auto(tasks, concurrency, callback) {
+ if (typeof concurrency !== 'number') {
// concurrency is optional, shift the args.
callback = concurrency;
concurrency = null;
}
- callback = once(callback || noop);
+ callback = once(callback || promiseCallback());
var numTasks = Object.keys(tasks).length;
if (!numTasks) {
return callback(null);
@@ -251,4 +250,6 @@ export default function (tasks, concurrency, callback) {
});
return result;
}
+
+ return callback[PROMISE_SYMBOL]
}
diff --git a/lib/autoInject.js b/lib/autoInject.js
index 004cfda..996fceb 100644
--- a/lib/autoInject.js
+++ b/lib/autoInject.js
@@ -54,6 +54,7 @@ function parseParams(func) {
* the tasks have been completed. It receives the `err` argument if any `tasks`
* pass an error to their callback, and a `results` object with any completed
* task results, similar to `auto`.
+ * @returns {Promise} a promise, if no callback is passed
* @example
*
* // The example from `auto` can be rewritten as follows:
@@ -142,5 +143,5 @@ export default function autoInject(tasks, callback) {
}
});
- auto(newTasks, callback);
+ return auto(newTasks, callback);
}
diff --git a/lib/compose.js b/lib/compose.js
index 1706013..ea97c43 100644
--- a/lib/compose.js
+++ b/lib/compose.js
@@ -6,6 +6,9 @@ import seq from './seq';
* follows. Composing functions `f()`, `g()`, and `h()` would produce the result
* of `f(g(h()))`, only this version uses callbacks to obtain the return values.
*
+ * If the last argument to the composed function is not a function, a promise
+ * is returned when you call it.
+ *
* Each function is executed with the `this` binding of the composed function.
*
* @name compose
@@ -35,6 +38,6 @@ import seq from './seq';
* // result now equals 15
* });
*/
-export default function(...args) {
+export default function compose(...args) {
return seq(...args.reverse());
}
diff --git a/lib/concat.js b/lib/concat.js
index 0a8251a..394e3c2 100644
--- a/lib/concat.js
+++ b/lib/concat.js
@@ -1,5 +1,5 @@
-import doLimit from './internal/doLimit';
import concatLimit from './concatLimit';
+import awaitify from './internal/awaitify'
/**
* Applies `iteratee` to each item in `coll`, concatenating the results. Returns
@@ -15,14 +15,18 @@ import concatLimit from './concatLimit';
* @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
* @param {AsyncFunction} iteratee - A function to apply to each item in `coll`,
* which should use an array as its result. Invoked with (item, callback).
- * @param {Function} [callback(err)] - A callback which is called after all the
+ * @param {Function} [callback] - A callback which is called after all the
* `iteratee` functions have finished, or an error occurs. Results is an array
* containing the concatenated results of the `iteratee` function. Invoked with
* (err, results).
+ * @returns A Promise, if no callback is passed
* @example
*
* async.concat(['dir1','dir2','dir3'], fs.readdir, function(err, files) {
* // files is now a list of filenames that exist in the 3 directories
* });
*/
-export default doLimit(concatLimit, Infinity);
+function concat(coll, iteratee, callback) {
+ return concatLimit(coll, Infinity, iteratee, callback)
+}
+export default awaitify(concat, 3);
diff --git a/lib/concatLimit.js b/lib/concatLimit.js
index 5dbbe8d..34c35df 100644
--- a/lib/concatLimit.js
+++ b/lib/concatLimit.js
@@ -1,6 +1,6 @@
-import noop from './internal/noop';
import wrapAsync from './internal/wrapAsync';
import mapLimit from './mapLimit';
+import awaitify from './internal/awaitify'
/**
* The same as [`concat`]{@link module:Collections.concat} but runs a maximum of `limit` async operations at a time.
@@ -19,11 +19,11 @@ import mapLimit from './mapLimit';
* `iteratee` functions have finished, or an error occurs. Results is an array
* containing the concatenated results of the `iteratee` function. Invoked with
* (err, results).
+ * @returns A Promise, if no callback is passed
*/
-export default function(coll, limit, iteratee, callback) {
- callback = callback || noop;
+function concatLimit(coll, limit, iteratee, callback) {
var _iteratee = wrapAsync(iteratee);
- mapLimit(coll, limit, (val, iterCb) => {
+ return mapLimit(coll, limit, (val, iterCb) => {
_iteratee(val, (err, ...args) => {
if (err) return iterCb(err);
return iterCb(null, args);
@@ -39,3 +39,4 @@ export default function(coll, limit, iteratee, callback) {
return callback(err, result);
});
}
+export default awaitify(concatLimit, 4)
diff --git a/lib/concatSeries.js b/lib/concatSeries.js
index ae1bd67..0b36803 100644
--- a/lib/concatSeries.js
+++ b/lib/concatSeries.js
@@ -1,5 +1,5 @@
-import doLimit from './internal/doLimit';
import concatLimit from './concatLimit';
+import awaitify from './internal/awaitify'
/**
* The same as [`concat`]{@link module:Collections.concat} but runs only a single async operation at a time.
@@ -14,9 +14,13 @@ import concatLimit from './concatLimit';
* @param {AsyncFunction} iteratee - A function to apply to each item in `coll`.
* The iteratee should complete with an array an array of results.
* Invoked with (item, callback).
- * @param {Function} [callback(err)] - A callback which is called after all the
+ * @param {Function} [callback] - A callback which is called after all the
* `iteratee` functions have finished, or an error occurs. Results is an array
* containing the concatenated results of the `iteratee` function. Invoked with
* (err, results).
+ * @returns A Promise, if no callback is passed
*/
-export default doLimit(concatLimit, 1);
+function concatSeries(coll, iteratee, callback) {
+ return concatLimit(coll, 1, iteratee, callback)
+}
+export default awaitify(concatSeries, 3);
diff --git a/lib/detect.js b/lib/detect.js
index 3e28f0e..4a6746a 100644
--- a/lib/detect.js
+++ b/lib/detect.js
@@ -1,5 +1,6 @@
import createTester from './internal/createTester';
-import doParallel from './internal/doParallel';
+import eachOf from './eachOf'
+import awaitify from './internal/awaitify'
/**
* Returns the first value in `coll` that passes an async truth test. The
@@ -26,6 +27,7 @@ import doParallel from './internal/doParallel';
* Result will be the first item in the array that passes the truth test
* (iteratee) or the value `undefined` if none passed. Invoked with
* (err, result).
+ * @returns A Promise, if no callback is passed
* @example
*
* async.detect(['file1','file2','file3'], function(filePath, callback) {
@@ -36,4 +38,7 @@ import doParallel from './internal/doParallel';
* // result now equals the first file in the list that exists
* });
*/
-export default doParallel(createTester(bool => bool, (res, item) => item));
+function detect(coll, iteratee, callback) {
+ return createTester(bool => bool, (res, item) => item)(eachOf, coll, iteratee, callback)
+}
+export default awaitify(detect, 3)
diff --git a/lib/detectLimit.js b/lib/detectLimit.js
index a0f9d89..7630d6d 100644
--- a/lib/detectLimit.js
+++ b/lib/detectLimit.js
@@ -1,5 +1,6 @@
import createTester from './internal/createTester';
-import doParallelLimit from './internal/doParallelLimit';
+import eachOfLimit from './internal/eachOfLimit'
+import awaitify from './internal/awaitify'
/**
* The same as [`detect`]{@link module:Collections.detect} but runs a maximum of `limit` async operations at a
@@ -22,5 +23,9 @@ import doParallelLimit from './internal/doParallelLimit';
* Result will be the first item in the array that passes the truth test
* (iteratee) or the value `undefined` if none passed. Invoked with
* (err, result).
+ * @returns a Promise if no callback is passed
*/
-export default doParallelLimit(createTester(bool => bool, (res, item) => item));
+function detectLimit(coll, limit, iteratee, callback) {
+ return createTester(bool => bool, (res, item) => item)(eachOfLimit(limit), coll, iteratee, callback)
+}
+export default awaitify(detectLimit, 4)
diff --git a/lib/detectSeries.js b/lib/detectSeries.js
index f563eae..e85c4f8 100644
--- a/lib/detectSeries.js
+++ b/lib/detectSeries.js
@@ -1,5 +1,6 @@
-import detectLimit from './detectLimit';
-import doLimit from './internal/doLimit';
+import createTester from './internal/createTester'
+import eachOfLimit from './internal/eachOfLimit'
+import awaitify from './internal/awaitify'
/**
* The same as [`detect`]{@link module:Collections.detect} but runs only a single async operation at a time.
@@ -20,5 +21,10 @@ import doLimit from './internal/doLimit';
* Result will be the first item in the array that passes the truth test
* (iteratee) or the value `undefined` if none passed. Invoked with
* (err, result).
+ * @returns a Promise if no callback is passed
*/
-export default doLimit(detectLimit, 1);
+function detectSeries(coll, iteratee, callback) {
+ return createTester(bool => bool, (res, item) => item)(eachOfLimit(1), coll, iteratee, callback)
+}
+
+export default awaitify(detectSeries, 3)
diff --git a/lib/doUntil.js b/lib/doUntil.js
index d2e5b04..a484df6 100644
--- a/lib/doUntil.js
+++ b/lib/doUntil.js
@@ -20,10 +20,11 @@ import wrapAsync from './internal/wrapAsync';
* function has passed and repeated execution of `iteratee` has stopped. `callback`
* will be passed an error and any arguments passed to the final `iteratee`'s
* callback. Invoked with (err, [results]);
+ * @returns {Promise} a promise, if no callback is passed
*/
export default function doUntil(iteratee, test, callback) {
const _test = wrapAsync(test)
- doWhilst(iteratee, (...args) => {
+ return doWhilst(iteratee, (...args) => {
const cb = args.pop()
_test(...args, (err, truth) => cb (err, !truth))
}, callback);
diff --git a/lib/doWhilst.js b/lib/doWhilst.js
index b3d52a5..3d9a1af 100644
--- a/lib/doWhilst.js
+++ b/lib/doWhilst.js
@@ -1,7 +1,6 @@
-import noop from './internal/noop';
-
import onlyOnce from './internal/onlyOnce';
import wrapAsync from './internal/wrapAsync';
+import awaitify from './internal/awaitify'
/**
* The post-check version of [`whilst`]{@link module:ControlFlow.whilst}. To reflect the difference in
@@ -24,10 +23,10 @@ import wrapAsync from './internal/wrapAsync';
* function has failed and repeated execution of `iteratee` has stopped.
* `callback` will be passed an error and any arguments passed to the final
* `iteratee`'s callback. Invoked with (err, [results]);
- * @return undefined
+ * @returns {Promise} a promise, if no callback is passed
*/
-export default function doWhilst(iteratee, test, callback) {
- callback = onlyOnce(callback || noop);
+function doWhilst(iteratee, test, callback) {
+ callback = onlyOnce(callback);
var _fn = wrapAsync(iteratee);
var _test = wrapAsync(test);
var results
@@ -48,3 +47,5 @@ export default function doWhilst(iteratee, test, callback) {
return check(null, true);
}
+
+export default awaitify(doWhilst, 3)
diff --git a/lib/each.js b/lib/each.js
index dc856ac..7f6e689 100644
--- a/lib/each.js
+++ b/lib/each.js
@@ -1,6 +1,7 @@
import eachOf from './eachOf';
import withoutIndex from './internal/withoutIndex';
import wrapAsync from './internal/wrapAsync'
+import awaitify from './internal/awaitify'
/**
* Applies the function `iteratee` to each item in `coll`, in parallel.
@@ -25,6 +26,7 @@ import wrapAsync from './internal/wrapAsync'
* If you need the index, use `eachOf`.
* @param {Function} [callback] - A callback which is called when all
* `iteratee` functions have finished, or an error occurs. Invoked with (err).
+ * @returns {Promise} a promise, if a callback is omitted
* @example
*
* // assuming openFiles is an array of file names and saveFile is a function
@@ -59,6 +61,8 @@ import wrapAsync from './internal/wrapAsync'
* }
* });
*/
-export default function eachLimit(coll, iteratee, callback) {
- eachOf(coll, withoutIndex(wrapAsync(iteratee)), callback);
+function eachLimit(coll, iteratee, callback) {
+ return eachOf(coll, withoutIndex(wrapAsync(iteratee)), callback);
}
+
+export default awaitify(eachLimit, 3)
diff --git a/lib/eachLimit.js b/lib/eachLimit.js
index e4d67cb..5c491e8 100644
--- a/lib/eachLimit.js
+++ b/lib/eachLimit.js
@@ -1,6 +1,7 @@
import eachOfLimit from './internal/eachOfLimit';
import withoutIndex from './internal/withoutIndex';
import wrapAsync from './internal/wrapAsync';
+import awaitify from './internal/awaitify'
/**
* The same as [`each`]{@link module:Collections.each} but runs a maximum of `limit` async operations at a time.
@@ -21,7 +22,9 @@ import wrapAsync from './internal/wrapAsync';
* Invoked with (item, callback).
* @param {Function} [callback] - A callback which is called when all
* `iteratee` functions have finished, or an error occurs. Invoked with (err).
+ * @returns {Promise} a promise, if a callback is omitted
*/
-export default function eachLimit(coll, limit, iteratee, callback) {
- eachOfLimit(limit)(coll, withoutIndex(wrapAsync(iteratee)), callback);
+function eachLimit(coll, limit, iteratee, callback) {
+ return eachOfLimit(limit)(coll, withoutIndex(wrapAsync(iteratee)), callback);
}
+export default awaitify(eachLimit, 4)
diff --git a/lib/eachOf.js b/lib/eachOf.js
index 070204b..0b847ae 100644
--- a/lib/eachOf.js
+++ b/lib/eachOf.js
@@ -1,15 +1,14 @@
import isArrayLike from './internal/isArrayLike';
import breakLoop from './internal/breakLoop';
import eachOfLimit from './eachOfLimit';
-import doLimit from './internal/doLimit';
-import noop from './internal/noop';
import once from './internal/once';
import onlyOnce from './internal/onlyOnce';
import wrapAsync from './internal/wrapAsync';
+import awaitify from './internal/awaitify'
// eachOf implementation optimized for array-likes
function eachOfArrayLike(coll, iteratee, callback) {
- callback = once(callback || noop);
+ callback = once(callback);
var index = 0,
completed = 0,
{length} = coll,
@@ -36,7 +35,9 @@ function eachOfArrayLike(coll, iteratee, callback) {
}
// a generic version of eachOf which can handle array, object, and iterator cases.
-var eachOfGeneric = doLimit(eachOfLimit, Infinity);
+function eachOfGeneric (coll, iteratee, callback) {
+ return eachOfLimit(coll, Infinity, iteratee, callback);
+}
/**
* Like [`each`]{@link module:Collections.each}, except that it passes the key (or index) as the second argument
@@ -56,6 +57,7 @@ var eachOfGeneric = doLimit(eachOfLimit, Infinity);
* Invoked with (item, key, callback).
* @param {Function} [callback] - A callback which is called when all
* `iteratee` functions have finished, or an error occurs. Invoked with (err).
+ * @returns {Promise} a promise, if a callback is omitted
* @example
*
* var obj = {dev: "/dev.json", test: "/test.json", prod: "/prod.json"};
@@ -77,7 +79,9 @@ var eachOfGeneric = doLimit(eachOfLimit, Infinity);
* doSomethingWith(configs);
* });
*/
-export default function(coll, iteratee, callback) {
+function eachOf(coll, iteratee, callback) {
var eachOfImplementation = isArrayLike(coll) ? eachOfArrayLike : eachOfGeneric;
- eachOfImplementation(coll, wrapAsync(iteratee), callback);
+ return eachOfImplementation(coll, wrapAsync(iteratee), callback);
}
+
+export default awaitify(eachOf, 3)
diff --git a/lib/eachOfLimit.js b/lib/eachOfLimit.js
index f439be6..f65d7d1 100644
--- a/lib/eachOfLimit.js
+++ b/lib/eachOfLimit.js
@@ -1,5 +1,6 @@
import _eachOfLimit from './internal/eachOfLimit';
import wrapAsync from './internal/wrapAsync';
+import awaitify from './internal/awaitify'
/**
* The same as [`eachOf`]{@link module:Collections.eachOf} but runs a maximum of `limit` async operations at a
@@ -20,7 +21,10 @@ import wrapAsync from './internal/wrapAsync';
* Invoked with (item, key, callback).
* @param {Function} [callback] - A callback which is called when all
* `iteratee` functions have finished, or an error occurs. Invoked with (err).
+ * @returns {Promise} a promise, if a callback is omitted
*/
-export default function eachOfLimit(coll, limit, iteratee, callback) {
- _eachOfLimit(limit)(coll, wrapAsync(iteratee), callback);
+function eachOfLimit(coll, limit, iteratee, callback) {
+ return _eachOfLimit(limit)(coll, wrapAsync(iteratee), callback);
}
+
+export default awaitify(eachOfLimit, 4)
diff --git a/lib/eachOfSeries.js b/lib/eachOfSeries.js
index d64e7ec..c48a66b 100644
--- a/lib/eachOfSeries.js
+++ b/lib/eachOfSeries.js
@@ -1,5 +1,5 @@
import eachOfLimit from './eachOfLimit';
-import doLimit from './internal/doLimit';
+import awaitify from './internal/awaitify'
/**
* The same as [`eachOf`]{@link module:Collections.eachOf} but runs only a single async operation at a time.
@@ -17,5 +17,9 @@ import doLimit from './internal/doLimit';
* Invoked with (item, key, callback).
* @param {Function} [callback] - A callback which is called when all `iteratee`
* functions have finished, or an error occurs. Invoked with (err).
+ * @returns {Promise} a promise, if a callback is omitted
*/
-export default doLimit(eachOfLimit, 1);
+function eachOfSeries(coll, iteratee, callback) {
+ return eachOfLimit(coll, 1, iteratee, callback)
+}
+export default awaitify(eachOfSeries, 3);
diff --git a/lib/eachSeries.js b/lib/eachSeries.js
index ae6f6c7..b4a86ba 100644
--- a/lib/eachSeries.js
+++ b/lib/eachSeries.js
@@ -1,5 +1,5 @@
import eachLimit from './eachLimit';
-import doLimit from './internal/doLimit';
+import awaitify from './internal/awaitify'
/**
* The same as [`each`]{@link module:Collections.each} but runs only a single async operation at a time.
@@ -19,5 +19,9 @@ import doLimit from './internal/doLimit';
* Invoked with (item, callback).
* @param {Function} [callback] - A callback which is called when all
* `iteratee` functions have finished, or an error occurs. Invoked with (err).
+ * @returns {Promise} a promise, if a callback is omitted
*/
-export default doLimit(eachLimit, 1);
+function eachSeries(coll, iteratee, callback) {
+ return eachLimit(coll, 1, iteratee, callback)
+}
+export default awaitify(eachSeries, 3);
diff --git a/lib/every.js b/lib/every.js
index be2bc4a..a5ce971 100644
--- a/lib/every.js
+++ b/lib/every.js
@@ -1,5 +1,6 @@
import createTester from './internal/createTester';
-import doParallel from './internal/doParallel';
+import eachOf from './eachOf'
+import awaitify from './internal/awaitify'
/**
* Returns `true` if every element in `coll` satisfies an async test. If any
@@ -19,6 +20,7 @@ import doParallel from './internal/doParallel';
* @param {Function} [callback] - A callback which is called after all the
* `iteratee` functions have finished. Result will be either `true` or `false`
* depending on the values of the async tests. Invoked with (err, result).
+ * @returns {Promise} a promise, if no callback provided
* @example
*
* async.every(['file1','file2','file3'], function(filePath, callback) {
@@ -29,4 +31,7 @@ import doParallel from './internal/doParallel';
* // if result is true then every file exists
* });
*/
-export default doParallel(createTester(bool => !bool, res => !res));
+function every(coll, iteratee, callback) {
+ return createTester(bool => !bool, res => !res)(eachOf, coll, iteratee, callback)
+}
+export default awaitify(every, 3);
diff --git a/lib/everyLimit.js b/lib/everyLimit.js
index 78ffa36..787c704 100644
--- a/lib/everyLimit.js
+++ b/lib/everyLimit.js
@@ -1,5 +1,6 @@
import createTester from './internal/createTester';
-import doParallelLimit from './internal/doParallelLimit';
+import eachOfLimit from './internal/eachOfLimit'
+import awaitify from './internal/awaitify'
/**
* The same as [`every`]{@link module:Collections.every} but runs a maximum of `limit` async operations at a time.
@@ -20,5 +21,9 @@ import doParallelLimit from './internal/doParallelLimit';
* @param {Function} [callback] - A callback which is called after all the
* `iteratee` functions have finished. Result will be either `true` or `false`
* depending on the values of the async tests. Invoked with (err, result).
+ * @returns {Promise} a promise, if no callback provided
*/
-export default doParallelLimit(createTester(bool => !bool, res => !res));
+function everyLimit(coll, limit, iteratee, callback) {
+ return createTester(bool => !bool, res => !res)(eachOfLimit(limit), coll, iteratee, callback)
+}
+export default awaitify(everyLimit, 4);
diff --git a/lib/everySeries.js b/lib/everySeries.js
index c450bff..07d2612 100644
--- a/lib/everySeries.js
+++ b/lib/everySeries.js
@@ -1,5 +1,6 @@
-import everyLimit from './everyLimit';
-import doLimit from './internal/doLimit';
+import createTester from './internal/createTester';
+import eachOfSeries from './eachOfSeries';
+import awaitify from './internal/awaitify';
/**
* The same as [`every`]{@link module:Collections.every} but runs only a single async operation at a time.
@@ -19,5 +20,9 @@ import doLimit from './internal/doLimit';
* @param {Function} [callback] - A callback which is called after all the
* `iteratee` functions have finished. Result will be either `true` or `false`
* depending on the values of the async tests. Invoked with (err, result).
+ * @returns {Promise} a promise, if no callback provided
*/
-export default doLimit(everyLimit, 1);
+function everySeries(coll, iteratee, callback) {
+ return createTester(bool => !bool, res => !res)(eachOfSeries, coll, iteratee, callback)
+}
+export default awaitify(everySeries, 3);
diff --git a/lib/filter.js b/lib/filter.js
index 692802b..b0f3029 100644
--- a/lib/filter.js
+++ b/lib/filter.js
@@ -1,5 +1,6 @@
-import filter from './internal/filter';
-import doParallel from './internal/doParallel';
+import _filter from './internal/filter';
+import eachOf from './eachOf'
+import awaitify from './internal/awaitify'
/**
* Returns a new array of all the values in `coll` which pass an async truth
@@ -18,6 +19,7 @@ import doParallel from './internal/doParallel';
* with a boolean argument once it has completed. Invoked with (item, callback).
* @param {Function} [callback] - A callback which is called after all the
* `iteratee` functions have finished. Invoked with (err, results).
+ * @returns {Promise} a promise, if no callback provided
* @example
*
* async.filter(['file1','file2','file3'], function(filePath, callback) {
@@ -28,4 +30,7 @@ import doParallel from './internal/doParallel';
* // results now equals an array of the existing files
* });
*/
-export default doParallel(filter);
+function filter (coll, iteratee, callback) {
+ return _filter(eachOf, coll, iteratee, callback)
+}
+export default awaitify(filter, 3);
diff --git a/lib/filterLimit.js b/lib/filterLimit.js
index 946002d..b421caa 100644
--- a/lib/filterLimit.js
+++ b/lib/filterLimit.js
@@ -1,5 +1,6 @@
-import filter from './internal/filter';
-import doParallelLimit from './internal/doParallelLimit';
+import _filter from './internal/filter';
+import eachOfLimit from './internal/eachOfLimit'
+import awaitify from './internal/awaitify'
/**
* The same as [`filter`]{@link module:Collections.filter} but runs a maximum of `limit` async operations at a
@@ -19,5 +20,9 @@ import doParallelLimit from './internal/doParallelLimit';
* with a boolean argument once it has completed. Invoked with (item, callback).
* @param {Function} [callback] - A callback which is called after all the
* `iteratee` functions have finished. Invoked with (err, results).
+ * @returns {Promise} a promise, if no callback provided
*/
-export default doParallelLimit(filter);
+function filterLimit (coll, limit, iteratee, callback) {
+ return _filter(eachOfLimit(limit), coll, iteratee, callback)
+}
+export default awaitify(filterLimit, 4);
diff --git a/lib/filterSeries.js b/lib/filterSeries.js
index 908afbc..f53c3d8 100644
--- a/lib/filterSeries.js
+++ b/lib/filterSeries.js
@@ -1,5 +1,6 @@
-import filterLimit from './filterLimit';
-import doLimit from './internal/doLimit';
+import _filter from './internal/filter';
+import eachOfSeries from './eachOfSeries'
+import awaitify from './internal/awaitify'
/**
* The same as [`filter`]{@link module:Collections.filter} but runs only a single async operation at a time.
@@ -17,5 +18,9 @@ import doLimit from './internal/doLimit';
* with a boolean argument once it has completed. Invoked with (item, callback).
* @param {Function} [callback] - A callback which is called after all the
* `iteratee` functions have finished. Invoked with (err, results)
+ * @returns {Promise} a promise, if no callback provided
*/
-export default doLimit(filterLimit, 1);
+function filterSeries (coll, iteratee, callback) {
+ return _filter(eachOfSeries, coll, iteratee, callback)
+}
+export default awaitify(filterSeries, 3);
diff --git a/lib/forever.js b/lib/forever.js
index fb69adf..4914c21 100644
--- a/lib/forever.js
+++ b/lib/forever.js
@@ -1,7 +1,7 @@
-import noop from './internal/noop';
import onlyOnce from './internal/onlyOnce';
import ensureAsync from './ensureAsync';
import wrapAsync from './internal/wrapAsync';
+import awaitify from './internal/awaitify'
/**
* Calls the asynchronous function `fn` with a callback parameter that allows it
@@ -19,6 +19,8 @@ import wrapAsync from './internal/wrapAsync';
* Invoked with (next).
* @param {Function} [errback] - when `fn` passes an error to it's callback,
* this function will be called, and execution stops. Invoked with (err).
+ * @returns {Promise} a promise that rejects if an error occurs and an errback
+ * is not passed
* @example
*
* async.forever(
@@ -32,8 +34,8 @@ import wrapAsync from './internal/wrapAsync';
* }
* );
*/
-export default function forever(fn, errback) {
- var done = onlyOnce(errback || noop);
+function forever(fn, errback) {
+ var done = onlyOnce(errback);
var task = wrapAsync(ensureAsync(fn));
function next(err) {
@@ -41,5 +43,6 @@ export default function forever(fn, errback) {
if (err === false) return;
task(next);
}
- next();
+ return next();
}
+export default awaitify(forever, 2)
diff --git a/lib/groupBy.js b/lib/groupBy.js
index 860a01f..2993367 100644
--- a/lib/groupBy.js
+++ b/lib/groupBy.js
@@ -1,4 +1,3 @@
-import doLimit from './internal/doLimit';
import groupByLimit from './groupByLimit';
/**
@@ -25,6 +24,7 @@ import groupByLimit from './groupByLimit';
* @param {Function} [callback] - A callback which is called when all `iteratee`
* functions have finished, or an error occurs. Result is an `Object` whoses
* properties are arrays of values which returned the corresponding key.
+ * @returns {Promise} a promise, if no callback is passed
* @example
*
* async.groupBy(['userId1', 'userId2', 'userId3'], function(userId, callback) {
@@ -37,4 +37,6 @@ import groupByLimit from './groupByLimit';
* // e.g. { 30: ['userId1', 'userId3'], 42: ['userId2']};
* });
*/
-export default doLimit(groupByLimit, Infinity);
+export default function groupBy (coll, iteratee, callback) {
+ return groupByLimit(coll, Infinity, iteratee, callback)
+}
diff --git a/lib/groupByLimit.js b/lib/groupByLimit.js
index f0402aa..24d5c40 100644
--- a/lib/groupByLimit.js
+++ b/lib/groupByLimit.js
@@ -1,6 +1,7 @@
-import noop from './internal/noop';
import mapLimit from './mapLimit';
import wrapAsync from './internal/wrapAsync';
+import awaitify from './internal/awaitify'
+
/**
* The same as [`groupBy`]{@link module:Collections.groupBy} but runs a maximum of `limit` async operations at a time.
*
@@ -19,11 +20,11 @@ import wrapAsync from './internal/wrapAsync';
* @param {Function} [callback] - A callback which is called when all `iteratee`
* functions have finished, or an error occurs. Result is an `Object` whoses
* properties are arrays of values which returned the corresponding key.
+ * @returns {Promise} a promise, if no callback is passed
*/
-export default function(coll, limit, iteratee, callback) {
- callback = callback || noop;
+function groupByLimit(coll, limit, iteratee, callback) {
var _iteratee = wrapAsync(iteratee);
- mapLimit(coll, limit, (val, iterCb) => {
+ return mapLimit(coll, limit, (val, iterCb) => {
_iteratee(val, (err, key) => {
if (err) return iterCb(err);
return iterCb(null, {key, val});
@@ -49,3 +50,5 @@ export default function(coll, limit, iteratee, callback) {
return callback(err, result);
});
}
+
+export default awaitify(groupByLimit, 4);
diff --git a/lib/groupBySeries.js b/lib/groupBySeries.js
index a093d7f..ee673e1 100644
--- a/lib/groupBySeries.js
+++ b/lib/groupBySeries.js
@@ -1,4 +1,3 @@
-import doLimit from './internal/doLimit';
import groupByLimit from './groupByLimit';
/**
@@ -11,7 +10,6 @@ import groupByLimit from './groupByLimit';
* @see [async.groupBy]{@link module:Collections.groupBy}
* @category Collection
* @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
- * @param {number} limit - The maximum number of async operations at a time.
* @param {AsyncFunction} iteratee - An async function to apply to each item in
* `coll`.
* The iteratee should complete with a `key` to group the value under.
@@ -19,5 +17,8 @@ import groupByLimit from './groupByLimit';
* @param {Function} [callback] - A callback which is called when all `iteratee`
* functions have finished, or an error occurs. Result is an `Object` whoses
* properties are arrays of values which returned the corresponding key.
+ * @returns {Promise} a promise, if no callback is passed
*/
-export default doLimit(groupByLimit, 1);
+export default function groupBySeries (coll, iteratee, callback) {
+ return groupByLimit(coll, 1, iteratee, callback)
+}
diff --git a/lib/internal/awaitify.js b/lib/internal/awaitify.js
new file mode 100644
index 0000000..57628de
--- /dev/null
+++ b/lib/internal/awaitify.js
@@ -0,0 +1,24 @@
+// conditionally promisify a function.
+// only return a promise if a callback is omitted
+export default function awaitify (asyncFn, arity = asyncFn.length) {
+ if (!arity) throw new Error('arity is undefined')
+ function awaitable (...args) {
+ if (typeof args[arity - 1] === 'function') {
+ return asyncFn.apply(this, args)
+ }
+
+ return new Promise((resolve, reject) => {
+ args[arity - 1] = (err, ...cbArgs) => {
+ if (err) return reject(err)
+ resolve(cbArgs.length > 1 ? cbArgs : cbArgs[0])
+ }
+ asyncFn.apply(this, args)
+ })
+ }
+
+ Object.defineProperty(awaitable, 'name', {
+ value: `awaitable(${asyncFn.name})`
+ })
+
+ return awaitable
+}
diff --git a/lib/internal/createTester.js b/lib/internal/createTester.js
index 4a5d39f..5858702 100644
--- a/lib/internal/createTester.js
+++ b/lib/internal/createTester.js
@@ -1,11 +1,11 @@
-import noop from './noop';
import breakLoop from './breakLoop';
+import wrapAsync from './wrapAsync'
export default function _createTester(check, getResult) {
- return (eachfn, arr, iteratee, cb) => {
- cb = cb || noop;
+ return (eachfn, arr, _iteratee, cb) => {
var testPassed = false;
var testResult;
+ const iteratee = wrapAsync(_iteratee)
eachfn(arr, (value, _, callback) => {
iteratee(value, (err, result) => {
if (err) return callback(err)
diff --git a/lib/internal/doLimit.js b/lib/internal/doLimit.js
deleted file mode 100644
index 70fb495..0000000
--- a/lib/internal/doLimit.js
+++ /dev/null
@@ -1,3 +0,0 @@
-export default function doLimit(fn, limit) {
- return (iterable, iteratee, cb) => fn(iterable, limit, iteratee, cb)
-}
diff --git a/lib/internal/doParallel.js b/lib/internal/doParallel.js
deleted file mode 100644
index 2b76b68..0000000
--- a/lib/internal/doParallel.js
+++ /dev/null
@@ -1,6 +0,0 @@
-import eachOf from '../eachOf';
-import wrapAsync from './wrapAsync';
-
-export default function doParallel(fn) {
- return (obj, iteratee, cb) => fn(eachOf, obj, wrapAsync(iteratee), cb);
-}
diff --git a/lib/internal/doParallelLimit.js b/lib/internal/doParallelLimit.js
deleted file mode 100644
index 5e2703a..0000000
--- a/lib/internal/doParallelLimit.js
+++ /dev/null
@@ -1,6 +0,0 @@
-import eachOfLimit from './eachOfLimit';
-import wrapAsync from './wrapAsync';
-
-export default function doParallelLimit(fn) {
- return (obj, limit, iteratee, cb) => fn(eachOfLimit(limit), obj, wrapAsync(iteratee), cb);
-}
diff --git a/lib/internal/eachOfLimit.js b/lib/internal/eachOfLimit.js
index 999cbfa..ec6c8be 100644
--- a/lib/internal/eachOfLimit.js
+++ b/lib/internal/eachOfLimit.js
@@ -1,4 +1,3 @@
-import noop from './noop';
import once from './once';
import iterator from './iterator';
@@ -10,7 +9,7 @@ import breakLoop from './breakLoop';
export default (limit) => {
return (obj, iteratee, callback) => {
- callback = once(callback || noop);
+ callback = once(callback);
if (limit <= 0) {
throw new RangeError('concurrency limit cannot be less than 1')
}
diff --git a/lib/internal/filter.js b/lib/internal/filter.js
index ab37390..15d7ae3 100644
--- a/lib/internal/filter.js
+++ b/lib/internal/filter.js
@@ -1,5 +1,4 @@
import isArrayLike from './isArrayLike';
-import noop from './noop';
import wrapAsync from './wrapAsync';
@@ -40,5 +39,5 @@ function filterGeneric(eachfn, coll, iteratee, callback) {
export default function _filter(eachfn, coll, iteratee, callback) {
var filter = isArrayLike(coll) ? filterArray : filterGeneric;
- return filter(eachfn, coll, wrapAsync(iteratee), callback || noop);
+ return filter(eachfn, coll, wrapAsync(iteratee), callback);
}
diff --git a/lib/internal/initialParams.js b/lib/internal/initialParams.js
index 4014785..9ea253a 100644
--- a/lib/internal/initialParams.js
+++ b/lib/internal/initialParams.js
@@ -1,6 +1,6 @@
export default function (fn) {
return function (...args/*, callback*/) {
var callback = args.pop();
- fn.call(this, args, callback);
+ return fn.call(this, args, callback);
};
}
diff --git a/lib/internal/map.js b/lib/internal/map.js
index 3da8d9c..092f76d 100644
--- a/lib/internal/map.js
+++ b/lib/internal/map.js
@@ -1,8 +1,6 @@
-import noop from './noop';
import wrapAsync from './wrapAsync';
export default function _asyncMap(eachfn, arr, iteratee, callback) {
- callback = callback || noop;
arr = arr || [];
var results = [];
var counter = 0;
diff --git a/lib/internal/noop.js b/lib/internal/noop.js
deleted file mode 100644
index ca6a744..0000000
--- a/lib/internal/noop.js
+++ /dev/null
@@ -1 +0,0 @@
-export default function noop() {}
diff --git a/lib/internal/once.js b/lib/internal/once.js
index 1293d5e..10ab26b 100644
--- a/lib/internal/once.js
+++ b/lib/internal/once.js
@@ -1,8 +1,10 @@
export default function once(fn) {
- return function (...args) {
+ function wrapper (...args) {
if (fn === null) return;
var callFn = fn;
fn = null;
callFn.apply(this, args);
- };
+ }
+ Object.assign(wrapper, fn)
+ return wrapper
}
diff --git a/lib/internal/parallel.js b/lib/internal/parallel.js
index 8abf0d1..790b6e8 100644
--- a/lib/internal/parallel.js
+++ b/lib/internal/parallel.js
@@ -1,9 +1,8 @@
import isArrayLike from './isArrayLike';
-import noop from './noop';
import wrapAsync from './wrapAsync';
+import awaitify from './awaitify'
-export default function _parallel(eachfn, tasks, callback) {
- callback = callback || noop;
+export default awaitify((eachfn, tasks, callback) => {
var results = isArrayLike(tasks) ? [] : {};
eachfn(tasks, (task, key, taskCb) => {
@@ -15,4 +14,4 @@ export default function _parallel(eachfn, tasks, callback) {
taskCb(err);
});
}, err => callback(err, results));
-}
+}, 3)
diff --git a/lib/internal/promiseCallback.js b/lib/internal/promiseCallback.js
new file mode 100644
index 0000000..685dd7a
--- /dev/null
+++ b/lib/internal/promiseCallback.js
@@ -0,0 +1,19 @@
+const PROMISE_SYMBOL = Symbol('promiseCallback')
+
+function promiseCallback () {
+ let resolve, reject
+ function callback (err, ...args) {
+ if (err) return reject(err)
+ resolve(args.length > 1 ? args : args[0])
+ }
+
+ callback[PROMISE_SYMBOL] = new Promise((res, rej) => {
+ resolve = res,
+ reject = rej
+ })
+
+ return callback
+}
+
+
+export { promiseCallback, PROMISE_SYMBOL }
diff --git a/lib/internal/queue.js b/lib/internal/queue.js
index 4c1f5cc..751b562 100644
--- a/lib/internal/queue.js
+++ b/lib/internal/queue.js
@@ -1,9 +1,10 @@
-import noop from './noop';
import onlyOnce from './onlyOnce';
import setImmediate from './setImmediate';
import DLL from './DoublyLinkedList';
import wrapAsync from './wrapAsync';
+const noop = () => {}
+
export default function queue(worker, concurrency, payload) {
if (concurrency == null) {
concurrency = 1;
diff --git a/lib/internal/reject.js b/lib/internal/reject.js
index 1522632..d0549cc 100644
--- a/lib/internal/reject.js
+++ b/lib/internal/reject.js
@@ -1,6 +1,8 @@
import filter from './filter';
+import wrapAsync from './wrapAsync'
-export default function reject(eachfn, arr, iteratee, callback) {
+export default function reject(eachfn, arr, _iteratee, callback) {
+ const iteratee = wrapAsync(_iteratee)
return filter(eachfn, arr, (value, cb) => {
iteratee(value, (err, v) => {
cb(err, !v);
diff --git a/lib/internal/wrapAsync.js b/lib/internal/wrapAsync.js
index 5c3edd9..270cf8f 100644
--- a/lib/internal/wrapAsync.js
+++ b/lib/internal/wrapAsync.js
@@ -13,6 +13,7 @@ function isAsyncIterable(obj) {
}
function wrapAsync(asyncFn) {
+ if (typeof asyncFn !== 'function') throw new Error('expected a function')
return isAsync(asyncFn) ? asyncify(asyncFn) : asyncFn;
}
diff --git a/lib/map.js b/lib/map.js
index 2512c32..c32bd2d 100644
--- a/lib/map.js
+++ b/lib/map.js
@@ -1,5 +1,6 @@
-import doParallel from './internal/doParallel';
-import map from './internal/map';
+import _map from './internal/map';
+import eachOf from './eachOf'
+import awaitify from './internal/awaitify'
/**
* Produces a new collection of values by mapping each value in `coll` through
@@ -31,10 +32,14 @@ import map from './internal/map';
* @param {Function} [callback] - A callback which is called when all `iteratee`
* functions have finished, or an error occurs. Results is an Array of the
* transformed items from the `coll`. Invoked with (err, results).
+ * @returns {Promise} a promise, if no callback is passed
* @example
*
* async.map(['file1','file2','file3'], fs.stat, function(err, results) {
* // results is now an array of stats for each file
* });
*/
-export default doParallel(map);
+function map (coll, iteratee, callback) {
+ return _map(eachOf, coll, iteratee, callback)
+}
+export default awaitify(map, 3);
diff --git a/lib/mapLimit.js b/lib/mapLimit.js
index 905edc6..63fade2 100644
--- a/lib/mapLimit.js
+++ b/lib/mapLimit.js
@@ -1,5 +1,6 @@
-import doParallelLimit from './internal/doParallelLimit';
-import map from './internal/map';
+import _map from './internal/map';
+import eachOfLimit from './internal/eachOfLimit'
+import awaitify from './internal/awaitify'
/**
* The same as [`map`]{@link module:Collections.map} but runs a maximum of `limit` async operations at a time.
@@ -19,5 +20,9 @@ import map from './internal/map';
* @param {Function} [callback] - A callback which is called when all `iteratee`
* functions have finished, or an error occurs. Results is an array of the
* transformed items from the `coll`. Invoked with (err, results).
+ * @returns {Promise} a promise, if no callback is passed
*/
-export default doParallelLimit(map);
+function mapLimit (coll, limit, iteratee, callback) {
+ return _map(eachOfLimit(limit), coll, iteratee, callback)
+}
+export default awaitify(mapLimit, 4);
diff --git a/lib/mapSeries.js b/lib/mapSeries.js
index 96b5f0a..55c6831 100644
--- a/lib/mapSeries.js
+++ b/lib/mapSeries.js
@@ -1,5 +1,6 @@
-import mapLimit from './mapLimit';
-import doLimit from './internal/doLimit';
+import _map from './internal/map';
+import eachOfSeries from './eachOfSeries'
+import awaitify from './internal/awaitify'
/**
* The same as [`map`]{@link module:Collections.map} but runs only a single async operation at a time.
@@ -18,5 +19,9 @@ import doLimit from './internal/doLimit';
* @param {Function} [callback] - A callback which is called when all `iteratee`
* functions have finished, or an error occurs. Results is an array of the
* transformed items from the `coll`. Invoked with (err, results).
+ * @returns {Promise} a promise, if no callback is passed
*/
-export default doLimit(mapLimit, 1);
+function mapSeries (coll, iteratee, callback) {
+ return _map(eachOfSeries, coll, iteratee, callback)
+}
+export default awaitify(mapSeries, 3);
diff --git a/lib/mapValues.js b/lib/mapValues.js
index d6a4ad2..79edfd4 100644
--- a/lib/mapValues.js
+++ b/lib/mapValues.js
@@ -1,6 +1,4 @@
import mapValuesLimit from './mapValuesLimit';
-import doLimit from './internal/doLimit';
-
/**
* A relative of [`map`]{@link module:Collections.map}, designed for use with objects.
@@ -29,6 +27,7 @@ import doLimit from './internal/doLimit';
* functions have finished, or an error occurs. `result` is a new object consisting
* of each key from `obj`, with each transformed value on the right-hand side.
* Invoked with (err, result).
+ * @returns {Promise} a promise, if no callback is passed
* @example
*
* async.mapValues({
@@ -46,5 +45,6 @@ import doLimit from './internal/doLimit';
* // }
* });
*/
-
-export default doLimit(mapValuesLimit, Infinity);
+export default function mapValues(obj, iteratee, callback) {
+ return mapValuesLimit(obj, Infinity, iteratee, callback)
+}
diff --git a/lib/mapValuesLimit.js b/lib/mapValuesLimit.js
index 2267aaf..af56f25 100644
--- a/lib/mapValuesLimit.js
+++ b/lib/mapValuesLimit.js
@@ -1,6 +1,5 @@
-import eachOfLimit from './eachOfLimit';
-
-import noop from './internal/noop';
+import eachOfLimit from './internal/eachOfLimit'
+import awaitify from './internal/awaitify'
import once from './internal/once';
import wrapAsync from './internal/wrapAsync';
@@ -24,12 +23,13 @@ import wrapAsync from './internal/wrapAsync';
* functions have finished, or an error occurs. `result` is a new object consisting
* of each key from `obj`, with each transformed value on the right-hand side.
* Invoked with (err, result).
+ * @returns {Promise} a promise, if no callback is passed
*/
-export default function mapValuesLimit(obj, limit, iteratee, callback) {
- callback = once(callback || noop);
+function mapValuesLimit(obj, limit, iteratee, callback) {
+ callback = once(callback);
var newObj = {};
var _iteratee = wrapAsync(iteratee)
- eachOfLimit(obj, limit, (val, key, next) => {
+ return eachOfLimit(limit)(obj, (val, key, next) => {
_iteratee(val, key, (err, result) => {
if (err) return next(err);
newObj[key] = result;
@@ -37,3 +37,5 @@ export default function mapValuesLimit(obj, limit, iteratee, callback) {
});
}, err => callback(err, newObj));
}
+
+export default awaitify(mapValuesLimit, 4)
diff --git a/lib/mapValuesSeries.js b/lib/mapValuesSeries.js
index ab0b8f8..59e4b1a 100644
--- a/lib/mapValuesSeries.js
+++ b/lib/mapValuesSeries.js
@@ -1,5 +1,4 @@
import mapValuesLimit from './mapValuesLimit';
-import doLimit from './internal/doLimit';
/**
* The same as [`mapValues`]{@link module:Collections.mapValues} but runs only a single async operation at a time.
@@ -19,5 +18,8 @@ import doLimit from './internal/doLimit';
* functions have finished, or an error occurs. `result` is a new object consisting
* of each key from `obj`, with each transformed value on the right-hand side.
* Invoked with (err, result).
+ * @returns {Promise} a promise, if no callback is passed
*/
-export default doLimit(mapValuesLimit, 1);
+export default function mapValuesSeries(obj, iteratee, callback) {
+ return mapValuesLimit(obj, 1, iteratee, callback)
+}
diff --git a/lib/parallel.js b/lib/parallel.js
index edf8be4..fafae9d 100644
--- a/lib/parallel.js
+++ b/lib/parallel.js
@@ -1,5 +1,5 @@
import eachOf from './eachOf';
-import parallel from './internal/parallel';
+import _parallel from './internal/parallel';
/**
* Run the `tasks` collection of functions in parallel, without waiting until
@@ -34,6 +34,7 @@ import parallel from './internal/parallel';
* functions have completed successfully. This function gets a results array
* (or object) containing all the result arguments passed to the task callbacks.
* Invoked with (err, results).
+ * @returns {Promise} a promise, if a callback is not passed
*
* @example
* async.parallel([
@@ -70,6 +71,6 @@ import parallel from './internal/parallel';
* // results is now equals to: {one: 1, two: 2}
* });
*/
-export default function parallelLimit(tasks, callback) {
- parallel(eachOf, tasks, callback);
+export default function parallel(tasks, callback) {
+ return _parallel(eachOf, tasks, callback);
}
diff --git a/lib/parallelLimit.js b/lib/parallelLimit.js
index 9a857b8..ee4335c 100644
--- a/lib/parallelLimit.js
+++ b/lib/parallelLimit.js
@@ -19,7 +19,8 @@ import parallel from './internal/parallel';
* functions have completed successfully. This function gets a results array
* (or object) containing all the result arguments passed to the task callbacks.
* Invoked with (err, results).
+ * @returns {Promise} a promise, if a callback is not passed
*/
export default function parallelLimit(tasks, limit, callback) {
- parallel(eachOfLimit(limit), tasks, callback);
+ return parallel(eachOfLimit(limit), tasks, callback);
}
diff --git a/lib/priorityQueue.js b/lib/priorityQueue.js
index aa9b578..4eaea38 100644
--- a/lib/priorityQueue.js
+++ b/lib/priorityQueue.js
@@ -1,7 +1,4 @@
-import noop from './internal/noop';
-
import setImmediate from './setImmediate';
-
import queue from './queue';
/**
@@ -32,8 +29,7 @@ export default function(worker, concurrency) {
var q = queue(worker, concurrency);
// Override push to accept second parameter representing priority
- q.push = function(data, priority, callback) {
- if (callback == null) callback = noop;
+ q.push = function(data, priority = 0, callback = () => {}) {
if (typeof callback !== 'function') {
throw new Error('task callback must be a function');
}
@@ -46,7 +42,6 @@ export default function(worker, concurrency) {
return setImmediate(() => q.drain());
}
- priority = priority || 0;
var nextNode = q._tasks.head;
while (nextNode && priority >= nextNode.priority) {
nextNode = nextNode.next;
diff --git a/lib/race.js b/lib/race.js
index 0593a72..05101a3 100644
--- a/lib/race.js
+++ b/lib/race.js
@@ -1,6 +1,6 @@
-import noop from './internal/noop';
import once from './internal/once';
import wrapAsync from './internal/wrapAsync';
+import awaitify from './internal/awaitify';
/**
* Runs the `tasks` array of functions in parallel, without waiting until the
@@ -38,11 +38,13 @@ import wrapAsync from './internal/wrapAsync';
* // the result will be equal to 'two' as it finishes earlier
* });
*/
-export default function race(tasks, callback) {
- callback = once(callback || noop);
+function race(tasks, callback) {
+ callback = once(callback);
if (!Array.isArray(tasks)) return callback(new TypeError('First argument to race must be an array of functions'));
if (!tasks.length) return callback();
for (var i = 0, l = tasks.length; i < l; i++) {
wrapAsync(tasks[i])(callback);
}
}
+
+export default awaitify(race, 2)
diff --git a/lib/reduce.js b/lib/reduce.js
index 1a6c036..571bc5a 100644
--- a/lib/reduce.js
+++ b/lib/reduce.js
@@ -1,7 +1,7 @@
import eachOfSeries from './eachOfSeries';
-import noop from './internal/noop';
import once from './internal/once';
import wrapAsync from './internal/wrapAsync';
+import awaitify from './internal/awaitify'
/**
* Reduces `coll` into a single value using an async `iteratee` to return each
@@ -32,6 +32,7 @@ import wrapAsync from './internal/wrapAsync';
* @param {Function} [callback] - A callback which is called after all the
* `iteratee` functions have finished. Result is the reduced value. Invoked with
* (err, result).
+ * @returns {Promise} a promise, if no callback is passed
* @example
*
* async.reduce([1,2,3], 0, function(memo, item, callback) {
@@ -43,13 +44,15 @@ import wrapAsync from './internal/wrapAsync';
* // result is now equal to the last value of memo, which is 6
* });
*/
-export default function reduce(coll, memo, iteratee, callback) {
- callback = once(callback || noop);
+function reduce(coll, memo, iteratee, callback) {
+ callback = once(callback);
var _iteratee = wrapAsync(iteratee);
- eachOfSeries(coll, (x, i, iterCb) => {
+ return eachOfSeries(coll, (x, i, iterCb) => {
_iteratee(memo, x, (err, v) => {
memo = v;
iterCb(err);
});
}, err => callback(err, memo));
}
+export default awaitify(reduce, 4)
+
diff --git a/lib/reduceRight.js b/lib/reduceRight.js
index dd56a88..994eaf9 100644
--- a/lib/reduceRight.js
+++ b/lib/reduceRight.js
@@ -21,8 +21,9 @@ import reduce from './reduce';
* @param {Function} [callback] - A callback which is called after all the
* `iteratee` functions have finished. Result is the reduced value. Invoked with
* (err, result).
+ * @returns {Promise} a promise, if no callback is passed
*/
export default function reduceRight (array, memo, iteratee, callback) {
var reversed = [...array].reverse();
- reduce(reversed, memo, iteratee, callback);
+ return reduce(reversed, memo, iteratee, callback);
}
diff --git a/lib/reject.js b/lib/reject.js
index cfac12d..c1de825 100644
--- a/lib/reject.js
+++ b/lib/reject.js
@@ -1,5 +1,6 @@
-import reject from './internal/reject';
-import doParallel from './internal/doParallel';
+import _reject from './internal/reject';
+import eachOf from './eachOf'
+import awaitify from './internal/awaitify'
/**
* The opposite of [`filter`]{@link module:Collections.filter}. Removes values that pass an `async` truth test.
@@ -17,6 +18,7 @@ import doParallel from './internal/doParallel';
* Invoked with (item, callback).
* @param {Function} [callback] - A callback which is called after all the
* `iteratee` functions have finished. Invoked with (err, results).
+ * @returns {Promise} a promise, if no callback is passed
* @example
*
* async.reject(['file1','file2','file3'], function(filePath, callback) {
@@ -28,4 +30,7 @@ import doParallel from './internal/doParallel';
* createFiles(results);
* });
*/
-export default doParallel(reject);
+function reject (coll, iteratee, callback) {
+ return _reject(eachOf, coll, iteratee, callback)
+}
+export default awaitify(reject, 3);
diff --git a/lib/rejectLimit.js b/lib/rejectLimit.js
index 76e6ffc..d58b291 100644
--- a/lib/rejectLimit.js
+++ b/lib/rejectLimit.js
@@ -1,6 +1,6 @@
-import reject from './internal/reject';
-import doParallelLimit from './internal/doParallelLimit';
-
+import _reject from './internal/reject';
+import eachOfLimit from './internal/eachOfLimit'
+import awaitify from './internal/awaitify'
/**
* The same as [`reject`]{@link module:Collections.reject} but runs a maximum of `limit` async operations at a
* time.
@@ -19,5 +19,9 @@ import doParallelLimit from './internal/doParallelLimit';
* Invoked with (item, callback).
* @param {Function} [callback] - A callback which is called after all the
* `iteratee` functions have finished. Invoked with (err, results).
+ * @returns {Promise} a promise, if no callback is passed
*/
-export default doParallelLimit(reject);
+function rejectLimit (coll, limit, iteratee, callback) {
+ return _reject(eachOfLimit(limit), coll, iteratee, callback)
+}
+export default awaitify(rejectLimit, 4);
diff --git a/lib/rejectSeries.js b/lib/rejectSeries.js
index 3f2d62f..56b08a3 100644
--- a/lib/rejectSeries.js
+++ b/lib/rejectSeries.js
@@ -1,5 +1,6 @@
-import rejectLimit from './rejectLimit';
-import doLimit from './internal/doLimit';
+import _reject from './internal/reject';
+import eachOfSeries from './eachOfSeries'
+import awaitify from './internal/awaitify'
/**
* The same as [`reject`]{@link module:Collections.reject} but runs only a single async operation at a time.
@@ -17,5 +18,9 @@ import doLimit from './internal/doLimit';
* Invoked with (item, callback).
* @param {Function} [callback] - A callback which is called after all the
* `iteratee` functions have finished. Invoked with (err, results).
+ * @returns {Promise} a promise, if no callback is passed
*/
-export default doLimit(rejectLimit, 1);
+function rejectSeries (coll, iteratee, callback) {
+ return _reject(eachOfSeries, coll, iteratee, callback)
+}
+export default awaitify(rejectSeries, 3);
diff --git a/lib/retry.js b/lib/retry.js
index 2a353dc..5ef6971 100644
--- a/lib/retry.js
+++ b/lib/retry.js
@@ -1,5 +1,5 @@
-import noop from './internal/noop';
import wrapAsync from './internal/wrapAsync';
+import { promiseCallback, PROMISE_SYMBOL } from './internal/promiseCallback';
function constant(value) {
return function () {
@@ -39,6 +39,7 @@ function constant(value) {
* task has succeeded, or after the final failed attempt. It receives the `err`
* and `result` arguments of the last attempt at completing the `task`. Invoked
* with (err, results).
+ * @returns {Promise} a promise if no callback provided
*
* @example
*
@@ -101,11 +102,11 @@ export default function retry(opts, task, callback) {
};
if (arguments.length < 3 && typeof opts === 'function') {
- callback = task || noop;
+ callback = task || promiseCallback();
task = opts;
} else {
parseTimes(options, opts);
- callback = callback || noop;
+ callback = callback || promiseCallback();
}
if (typeof task !== 'function') {
@@ -129,6 +130,7 @@ export default function retry(opts, task, callback) {
}
retryAttempt();
+ return callback[PROMISE_SYMBOL]
}
function parseTimes(acc, t) {
diff --git a/lib/retryable.js b/lib/retryable.js
index 9422eed..ad99801 100644
--- a/lib/retryable.js
+++ b/lib/retryable.js
@@ -1,6 +1,7 @@
import retry from './retry';
import initialParams from './internal/initialParams';
-import wrapAsync from './internal/wrapAsync';
+import {default as wrapAsync, isAsync} from './internal/wrapAsync';
+import { promiseCallback, PROMISE_SYMBOL } from './internal/promiseCallback';
/**
* A close relative of [`retry`]{@link module:ControlFlow.retry}. This method
@@ -14,7 +15,8 @@ import wrapAsync from './internal/wrapAsync';
* @see [async.retry]{@link module:ControlFlow.retry}
* @category Control Flow
* @param {Object|number} [opts = {times: 5, interval: 0}| 5] - optional
- * options, exactly the same as from `retry`
+ * options, exactly the same as from `retry`, except for a `opts.arity` that
+ * is the arity of the `task` function, defaulting to `task.length`
* @param {AsyncFunction} task - the asynchronous function to wrap.
* This function will be passed any arguments passed to the returned wrapper.
* Invoked with (...args, callback).
@@ -30,13 +32,21 @@ import wrapAsync from './internal/wrapAsync';
* })]
* }, callback);
*/
-export default function (opts, task) {
+export default function retryable (opts, task) {
if (!task) {
task = opts;
opts = null;
}
+ let arity = (opts && opts.arity) || task.length
+ if (isAsync(task)) {
+ arity += 1
+ }
var _task = wrapAsync(task);
return initialParams((args, callback) => {
+ if (args.length < arity - 1 || callback == null) {
+ args.push(callback)
+ callback = promiseCallback()
+ }
function taskFn(cb) {
_task(...args, cb);
}
@@ -44,5 +54,6 @@ export default function (opts, task) {
if (opts) retry(opts, taskFn, callback);
else retry(taskFn, callback);
+ return callback[PROMISE_SYMBOL]
});
}
diff --git a/lib/seq.js b/lib/seq.js
index 1363cbd..6c9ede7 100644
--- a/lib/seq.js
+++ b/lib/seq.js
@@ -1,6 +1,6 @@
-import noop from './internal/noop';
import reduce from './reduce';
import wrapAsync from './internal/wrapAsync';
+import { promiseCallback, PROMISE_SYMBOL } from './internal/promiseCallback';
/**
* Version of the compose function that is more natural to read. Each function
@@ -49,7 +49,7 @@ export default function seq(...functions) {
if (typeof cb == 'function') {
args.pop();
} else {
- cb = noop;
+ cb = promiseCallback();
}
reduce(_functions, args, (newargs, fn, iterCb) => {
@@ -58,5 +58,7 @@ export default function seq(...functions) {
}));
},
(err, results) => cb(err, ...results));
+
+ return cb[PROMISE_SYMBOL]
};
}
diff --git a/lib/series.js b/lib/series.js
index 539a1e7..71367a9 100644
--- a/lib/series.js
+++ b/lib/series.js
@@ -1,4 +1,4 @@
-import parallel from './internal/parallel';
+import _parallel from './internal/parallel';
import eachOfSeries from './eachOfSeries';
/**
@@ -34,6 +34,7 @@ import eachOfSeries from './eachOfSeries';
* functions have completed. This function gets a results array (or object)
* containing all the result arguments passed to the `task` callbacks. Invoked
* with (err, result).
+ * @return {Promise} a promise, if no callback is passed
* @example
* async.series([
* function(callback) {
@@ -66,5 +67,5 @@ import eachOfSeries from './eachOfSeries';
* });
*/
export default function series(tasks, callback) {
- parallel(eachOfSeries, tasks, callback);
+ return _parallel(eachOfSeries, tasks, callback);
}
diff --git a/lib/some.js b/lib/some.js
index 65543bb..378ccdf 100644
--- a/lib/some.js
+++ b/lib/some.js
@@ -1,5 +1,6 @@
import createTester from './internal/createTester';
-import doParallel from './internal/doParallel';
+import eachOf from './eachOf'
+import awaitify from './internal/awaitify'
/**
* Returns `true` if at least one element in the `coll` satisfies an async test.
@@ -21,6 +22,7 @@ import doParallel from './internal/doParallel';
* iteratee returns `true`, or after all the iteratee functions have finished.
* Result will be either `true` or `false` depending on the values of the async
* tests. Invoked with (err, result).
+ * @returns {Promise} a promise, if no callback provided
* @example
*
* async.some(['file1','file2','file3'], function(filePath, callback) {
@@ -31,4 +33,7 @@ import doParallel from './internal/doParallel';
* // if result is true then at least one of the files exists
* });
*/
-export default doParallel(createTester(Boolean, res => res));
+function some(coll, iteratee, callback) {
+ return createTester(Boolean, res => res)(eachOf, coll, iteratee, callback)
+}
+export default awaitify(some, 3);
diff --git a/lib/someLimit.js b/lib/someLimit.js
index fb6841c..2defb28 100644
--- a/lib/someLimit.js
+++ b/lib/someLimit.js
@@ -1,5 +1,6 @@
import createTester from './internal/createTester';
-import doParallelLimit from './internal/doParallelLimit';
+import eachOfLimit from './internal/eachOfLimit'
+import awaitify from './internal/awaitify'
/**
* The same as [`some`]{@link module:Collections.some} but runs a maximum of `limit` async operations at a time.
@@ -21,5 +22,9 @@ import doParallelLimit from './internal/doParallelLimit';
* iteratee returns `true`, or after all the iteratee functions have finished.
* Result will be either `true` or `false` depending on the values of the async
* tests. Invoked with (err, result).
+ * @returns {Promise} a promise, if no callback provided
*/
-export default doParallelLimit(createTester(Boolean, res => res));
+function someLimit(coll, limit, iteratee, callback) {
+ return createTester(Boolean, res => res)(eachOfLimit(limit), coll, iteratee, callback)
+}
+export default awaitify(someLimit, 4);
diff --git a/lib/someSeries.js b/lib/someSeries.js
index c05ca1f..7842124 100644
--- a/lib/someSeries.js
+++ b/lib/someSeries.js
@@ -1,5 +1,6 @@
-import someLimit from './someLimit';
-import doLimit from './internal/doLimit';
+import createTester from './internal/createTester';
+import eachOfSeries from './eachOfSeries';
+import awaitify from './internal/awaitify';
/**
* The same as [`some`]{@link module:Collections.some} but runs only a single async operation at a time.
@@ -20,5 +21,9 @@ import doLimit from './internal/doLimit';
* iteratee returns `true`, or after all the iteratee functions have finished.
* Result will be either `true` or `false` depending on the values of the async
* tests. Invoked with (err, result).
+ * @returns {Promise} a promise, if no callback provided
*/
-export default doLimit(someLimit, 1);
+function someSeries(coll, iteratee, callback) {
+ return createTester(Boolean, res => res)(eachOfSeries, coll, iteratee, callback)
+}
+export default awaitify(someSeries, 3);
diff --git a/lib/sortBy.js b/lib/sortBy.js
index ba2a804..ec724b6 100644
--- a/lib/sortBy.js
+++ b/lib/sortBy.js
@@ -1,5 +1,6 @@
import map from './map';
import wrapAsync from './internal/wrapAsync';
+import awaitify from './internal/awaitify'
/**
* Sorts a list by the results of running each `coll` value through an async
@@ -20,6 +21,7 @@ import wrapAsync from './internal/wrapAsync';
* `iteratee` functions have finished, or an error occurs. Results is the items
* from the original `coll` sorted by the values returned by the `iteratee`
* calls. Invoked with (err, results).
+ * @returns {Promise} a promise, if no callback passed
* @example
*
* async.sortBy(['file1','file2','file3'], function(file, callback) {
@@ -48,9 +50,9 @@ import wrapAsync from './internal/wrapAsync';
* // result callback
* });
*/
-export default function sortBy (coll, iteratee, callback) {
+function sortBy (coll, iteratee, callback) {
var _iteratee = wrapAsync(iteratee);
- map(coll, (x, iterCb) => {
+ return map(coll, (x, iterCb) => {
_iteratee(x, (err, criteria) => {
if (err) return iterCb(err);
iterCb(null, {value: x, criteria});
@@ -65,3 +67,4 @@ export default function sortBy (coll, iteratee, callback) {
return a < b ? -1 : a > b ? 1 : 0;
}
}
+export default awaitify(sortBy, 3)
diff --git a/lib/times.js b/lib/times.js
index ebd336c..15e798f 100644
--- a/lib/times.js
+++ b/lib/times.js
@@ -1,5 +1,4 @@
import timesLimit from './timesLimit';
-import doLimit from './internal/doLimit';
/**
* Calls the `iteratee` function `n` times, and accumulates results in the same
@@ -15,6 +14,7 @@ import doLimit from './internal/doLimit';
* @param {AsyncFunction} iteratee - The async function to call `n` times.
* Invoked with the iteration index and a callback: (n, next).
* @param {Function} callback - see {@link module:Collections.map}.
+ * @returns {Promise} a promise, if no callback is provided
* @example
*
* // Pretend this is some complicated async factory
@@ -33,4 +33,6 @@ import doLimit from './internal/doLimit';
* // we should now have 5 users
* });
*/
-export default doLimit(timesLimit, Infinity);
+export default function times (n, iteratee, callback) {
+ return timesLimit(n, Infinity, iteratee, callback)
+}
diff --git a/lib/timesLimit.js b/lib/timesLimit.js
index bb4a1fe..8880ccf 100644
--- a/lib/timesLimit.js
+++ b/lib/timesLimit.js
@@ -17,8 +17,9 @@ import wrapAsync from './internal/wrapAsync';
* @param {AsyncFunction} iteratee - The async function to call `n` times.
* Invoked with the iteration index and a callback: (n, next).
* @param {Function} callback - see [async.map]{@link module:Collections.map}.
+ * @returns {Promise} a promise, if no callback is provided
*/
-export default function timeLimit(count, limit, iteratee, callback) {
+export default function timesLimit(count, limit, iteratee, callback) {
var _iteratee = wrapAsync(iteratee);
- mapLimit(range(count), limit, _iteratee, callback);
+ return mapLimit(range(count), limit, _iteratee, callback);
}
diff --git a/lib/timesSeries.js b/lib/timesSeries.js
index 17ec0ca..b56f6ec 100644
--- a/lib/timesSeries.js
+++ b/lib/timesSeries.js
@@ -1,5 +1,4 @@
import timesLimit from './timesLimit';
-import doLimit from './internal/doLimit';
/**
* The same as [times]{@link module:ControlFlow.times} but runs only a single async operation at a time.
@@ -14,5 +13,8 @@ import doLimit from './internal/doLimit';
* @param {AsyncFunction} iteratee - The async function to call `n` times.
* Invoked with the iteration index and a callback: (n, next).
* @param {Function} callback - see {@link module:Collections.map}.
+ * @returns {Promise} a promise, if no callback is provided
*/
-export default doLimit(timesLimit, 1);
+export default function timesSeries (n, iteratee, callback) {
+ return timesLimit(n, 1, iteratee, callback)
+}
diff --git a/lib/transform.js b/lib/transform.js
index 821a0fa..786f5d3 100644
--- a/lib/transform.js
+++ b/lib/transform.js
@@ -1,7 +1,7 @@
import eachOf from './eachOf';
-import noop from './internal/noop';
import once from './internal/once';
import wrapAsync from './internal/wrapAsync';
+import { promiseCallback, PROMISE_SYMBOL } from './internal/promiseCallback';
/**
* A relative of `reduce`. Takes an Object or Array, and iterates over each
@@ -22,6 +22,7 @@ import wrapAsync from './internal/wrapAsync';
* @param {Function} [callback] - A callback which is called after all the
* `iteratee` functions have finished. Result is the transformed accumulator.
* Invoked with (err, result).
+ * @returns {Promise} a promise, if no callback provided
* @example
*
* async.transform([1,2,3], function(acc, item, index, callback) {
@@ -46,15 +47,16 @@ import wrapAsync from './internal/wrapAsync';
* })
*/
export default function transform (coll, accumulator, iteratee, callback) {
- if (arguments.length <= 3) {
+ if (arguments.length <= 3 && typeof accumulator === 'function') {
callback = iteratee;
iteratee = accumulator;
accumulator = Array.isArray(coll) ? [] : {};
}
- callback = once(callback || noop);
+ callback = once(callback || promiseCallback());
var _iteratee = wrapAsync(iteratee);
eachOf(coll, (v, k, cb) => {
_iteratee(accumulator, v, k, cb);
}, err => callback(err, accumulator));
+ return callback[PROMISE_SYMBOL]
}
diff --git a/lib/tryEach.js b/lib/tryEach.js
index af885dc..6677c9d 100644
--- a/lib/tryEach.js
+++ b/lib/tryEach.js
@@ -1,6 +1,6 @@
import eachSeries from './eachSeries';
-import noop from './internal/noop';
import wrapAsync from './internal/wrapAsync';
+import awaitify from './internal/awaitify'
/**
* It runs each task in series but stops whenever any of the functions were
@@ -21,6 +21,7 @@ import wrapAsync from './internal/wrapAsync';
* 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).
+ * @returns {Promise} a promise, if no callback is passed
* @example
* async.tryEach([
* function getDataFromFirstWebsite(callback) {
@@ -39,11 +40,10 @@ import wrapAsync from './internal/wrapAsync';
* });
*
*/
-export default function tryEach(tasks, callback) {
+function tryEach(tasks, callback) {
var error = null;
var result;
- callback = callback || noop;
- eachSeries(tasks, (task, taskCb) => {
+ return eachSeries(tasks, (task, taskCb) => {
wrapAsync(task)((err, ...args) => {
if (args.length < 2) {
[result] = args;
@@ -55,3 +55,5 @@ export default function tryEach(tasks, callback) {
});
}, () => callback(error, result));
}
+
+export default awaitify(tryEach)
diff --git a/lib/until.js b/lib/until.js
index 37d8922..0c407a3 100644
--- a/lib/until.js
+++ b/lib/until.js
@@ -22,6 +22,7 @@ import wrapAsync from './internal/wrapAsync';
* function has passed and repeated execution of `iteratee` has stopped. `callback`
* will be passed an error and any arguments passed to the final `iteratee`'s
* callback. Invoked with (err, [results]);
+ * @returns {Promise} a promise, if a callback is not passed
*
* @example
* const results = []
@@ -39,5 +40,5 @@ import wrapAsync from './internal/wrapAsync';
*/
export default function until(test, iteratee, callback) {
const _test = wrapAsync(test)
- whilst((cb) => _test((err, truth) => cb (err, !truth)), iteratee, callback);
+ return whilst((cb) => _test((err, truth) => cb (err, !truth)), iteratee, callback);
}
diff --git a/lib/waterfall.js b/lib/waterfall.js
index f4c3ddc..f9a6c24 100644
--- a/lib/waterfall.js
+++ b/lib/waterfall.js
@@ -1,8 +1,8 @@
-import noop from './internal/noop';
import once from './internal/once';
import onlyOnce from './internal/onlyOnce';
import wrapAsync from './internal/wrapAsync';
+import awaitify from './internal/awaitify'
/**
* Runs the `tasks` array of functions in series, each passing their results to
@@ -61,8 +61,8 @@ import wrapAsync from './internal/wrapAsync';
* callback(null, 'done');
* }
*/
-export default function(tasks, callback) {
- callback = once(callback || noop);
+function waterfall (tasks, callback) {
+ callback = once(callback);
if (!Array.isArray(tasks)) return callback(new Error('First argument to waterfall must be an array of functions'));
if (!tasks.length) return callback();
var taskIndex = 0;
@@ -82,3 +82,5 @@ export default function(tasks, callback) {
nextTask([]);
}
+
+export default awaitify(waterfall)
diff --git a/lib/whilst.js b/lib/whilst.js
index d42e6a7..1013d37 100644
--- a/lib/whilst.js
+++ b/lib/whilst.js
@@ -1,7 +1,6 @@
-import noop from './internal/noop';
-
import onlyOnce from './internal/onlyOnce';
import wrapAsync from './internal/wrapAsync';
+import awaitify from './internal/awaitify';
/**
* Repeatedly call `iteratee`, while `test` returns `true`. Calls `callback` when
@@ -20,7 +19,7 @@ import wrapAsync from './internal/wrapAsync';
* function has failed and repeated execution of `iteratee` has stopped. `callback`
* will be passed an error and any arguments passed to the final `iteratee`'s
* callback. Invoked with (err, [results]);
- * @returns undefined
+ * @returns {Promise} a promise, if no callback is passed
* @example
*
* var count = 0;
@@ -37,8 +36,8 @@ import wrapAsync from './internal/wrapAsync';
* }
* );
*/
-export default function whilst(test, iteratee, callback) {
- callback = onlyOnce(callback || noop);
+function whilst(test, iteratee, callback) {
+ callback = onlyOnce(callback);
var _fn = wrapAsync(iteratee);
var _test = wrapAsync(test);
var results
@@ -59,3 +58,4 @@ export default function whilst(test, iteratee, callback) {
return _test(check);
}
+export default awaitify(whilst, 3)
diff --git a/test/asyncFunctions.js b/test/asyncFunctions.js
index 6bd7a8d..e24bd0c 100644
--- a/test/asyncFunctions.js
+++ b/test/asyncFunctions.js
@@ -27,6 +27,9 @@ describe('async function support', function () {
if (supportsAsync()) {
require('./es2017/asyncFunctions.js').call(this);
+ describe('awaitable functions', () => {
+ require('./es2017/awaitableFunctions.js').call(this);
+ });
} else {
it('should not test async functions in this environment');
}
diff --git a/test/es2017/awaitableFunctions.js b/test/es2017/awaitableFunctions.js
new file mode 100644
index 0000000..b45b56c
--- /dev/null
+++ b/test/es2017/awaitableFunctions.js
@@ -0,0 +1,579 @@
+var async = require('../../lib');
+const {expect} = require('chai');
+const {default: wrapAsync} = require('../../lib/internal/wrapAsync')
+
+
+module.exports = function () {
+ async function asyncIdentity(val) {
+ var res = await Promise.resolve(val);
+ return res;
+ }
+
+ const input = [1, 2, 3];
+ const inputObj = {a: 1, b: 2, c: 3};
+
+ it('asyncify should not add an additional level of wrapping', () => {
+ const wrapped = wrapAsync(async.each)
+ let sameStack = false
+ wrapped([1], (val, cb) => cb(), () => {sameStack = true})
+ expect(sameStack).to.equal(true)
+ })
+
+ it('should throw as expected (async)', async () => {
+ try {
+ await async.each(input, async val => { throw new Error(val) });
+ } catch (e) {
+ var thrown = e
+ }
+ expect(thrown).to.be.an('error')
+ });
+
+ it('should throw as expected (callback)', async () => {
+ let thrown
+ await async.each(input, (val) => {
+ throw new Error(val)
+ }).catch(e => {thrown = e})
+ expect(thrown).to.be.an('error')
+ })
+
+ it('should throw as expected (callback, try/catch)', async () => {
+ try {
+ await async.each(input, (val, cb) => { cb(new Error(val)) });
+ } catch (e) {
+ var thrown = e
+ }
+ expect(thrown).to.be.an('error')
+ });
+
+ /*
+ * Collections
+ */
+
+ it('should return a Promise: each', async () => {
+ expect (async.each.name).to.contain('each')
+ const calls = []
+ await async.each(input, async val => { calls.push(val) });
+ expect(calls).to.eql([1, 2, 3])
+ expect(async.each(input, asyncIdentity) instanceof Promise).to.equal(true)
+ });
+ it('should return a Promise: eachSeries', async () => {
+ expect (async.eachSeries.name).to.contain('eachSeries')
+ const calls = []
+ await async.eachSeries(input, async val => { calls.push(val) });
+ expect(calls).to.eql([1, 2, 3])
+ });
+ it('should return a Promise: eachLimit', async () => {
+ expect (async.eachLimit.name).to.contain('eachLimit')
+ const calls = []
+ await async.eachLimit(input, 1, async val => { calls.push(val) });
+ expect(calls).to.eql([1, 2, 3])
+ });
+
+ it('should return a Promise: eachOf', async () => {
+ expect (async.eachOf.name).to.contain('eachOf')
+ const calls = []
+ await async.eachOf(inputObj, async (...args) => { calls.push(args) });
+ expect(calls).to.eql([[1, 'a'], [2, 'b'], [3, 'c']])
+ });
+ it('should return a Promise: eachOfSeries', async () => {
+ expect (async.eachOfSeries.name).to.contain('eachOfSeries')
+ const calls = []
+ await async.eachOfSeries(inputObj, async (...args) => { calls.push(args) });
+ expect(calls).to.eql([[1, 'a'], [2, 'b'], [3, 'c']])
+ });
+ it('should return a Promise: eachOfLimit', async () => {
+ expect (async.eachOfLimit.name).to.contain('eachOfLimit')
+ const calls = []
+ await async.eachOfLimit(inputObj, 1, async (...args) => { calls.push(args) });
+ expect(calls).to.eql([[1, 'a'], [2, 'b'], [3, 'c']])
+ });
+
+ it('should return a Promise: concat', async () => {
+ expect (async.concat.name).to.contain('concat')
+ const calls = []
+ await async.concat(inputObj, async (...args) => { calls.push(args) });
+ expect(calls).to.eql([[1], [2], [3]])
+ });
+ it('should return a Promise: concatSeries', async () => {
+ expect (async.concatSeries.name).to.contain('concatSeries')
+ const calls = []
+ await async.concatSeries(inputObj, async (...args) => { calls.push(args) });
+ expect(calls).to.eql([[1], [2], [3]])
+ });
+ it('should return a Promise: concatLimit', async () => {
+ expect (async.concatLimit.name).to.contain('concatLimit')
+ const calls = []
+ await async.concatLimit(inputObj, 1, async (...args) => { calls.push(args) });
+ expect(calls).to.eql([[1], [2], [3]])
+ });
+
+ it('should return a Promise: detect', async () => {
+ expect (async.detect.name).to.contain('detect')
+ const calls = []
+ await async.detect(input, async (...args) => { calls.push(args); return args[0] === 3 });
+ expect(calls).to.eql([[1], [2], [3]])
+ });
+ it('should return a Promise: detectSeries', async () => {
+ expect (async.detectSeries.name).to.contain('detectSeries')
+ const calls = []
+ await async.detectSeries(input, async (...args) => { calls.push(args); return args[0] === 3 });
+ expect(calls).to.eql([[1], [2], [3]])
+ });
+ it('should return a Promise: detectLimit', async () => {
+ expect (async.detectLimit.name).to.contain('detectLimit')
+ const calls = []
+ await async.detectLimit(input, 1, async (...args) => { calls.push(args); return args[0] === 3 });
+ expect(calls).to.eql([[1], [2], [3]])
+ });
+
+ it('should return a Promise: every', async () => {
+ expect (async.every.name).to.contain('every')
+ const calls = []
+ await async.every(input, async (...args) => { calls.push(args); return args[0] !== 3 });
+ expect(calls).to.eql([[1], [2], [3]])
+ });
+ it('should return a Promise: everySeries', async () => {
+ expect (async.everySeries.name).to.contain('everySeries')
+ const calls = []
+ await async.everySeries(input, async (...args) => { calls.push(args); return args[0] !== 3 });
+ expect(calls).to.eql([[1], [2], [3]])
+ });
+ it('should return a Promise: everyLimit', async () => {
+ expect (async.everyLimit.name).to.contain('everyLimit')
+ const calls = []
+ await async.everyLimit(input, 1, async (...args) => { calls.push(args); return args[0] !== 3 });
+ expect(calls).to.eql([[1], [2], [3]])
+ });
+
+ it('should return a Promise: filter', async () => {
+ expect (async.filter.name).to.contain('filter')
+ const calls = []
+ await async.filter(inputObj, async (...args) => { calls.push(args) });
+ expect(calls).to.eql([[1], [2], [3]])
+ });
+ it('should return a Promise: filterSeries', async () => {
+ expect (async.filterSeries.name).to.contain('filterSeries')
+ const calls = []
+ await async.filterSeries(inputObj, async (...args) => { calls.push(args) });
+ expect(calls).to.eql([[1], [2], [3]])
+ });
+ it('should return a Promise: filterLimit', async () => {
+ expect (async.filterLimit.name).to.contain('filterLimit')
+ const calls = []
+ await async.filterLimit(inputObj, 1, async (...args) => { calls.push(args) });
+ expect(calls).to.eql([[1], [2], [3]])
+ });
+
+ it('should return a Promise: groupBy', async () => {
+ expect (async.groupBy.name).to.contain('groupBy')
+ const calls = []
+ await async.groupBy(inputObj, async (...args) => { calls.push(args) });
+ expect(calls).to.eql([[1], [2], [3]])
+ });
+ it('should return a Promise: groupBySeries', async () => {
+ expect (async.groupBySeries.name).to.contain('groupBySeries')
+ const calls = []
+ await async.groupBySeries(inputObj, async (...args) => { calls.push(args) });
+ expect(calls).to.eql([[1], [2], [3]])
+ });
+ it('should return a Promise: groupByLimit', async () => {
+ expect (async.groupByLimit.name).to.contain('groupByLimit')
+ const calls = []
+ await async.groupByLimit(inputObj, 1, async (...args) => { calls.push(args) });
+ expect(calls).to.eql([[1], [2], [3]])
+ });
+
+ it('should return a Promise: map', async () => {
+ expect (async.map.name).to.contain('map')
+ const calls = []
+ await async.map(inputObj, async (...args) => { calls.push(args) });
+ expect(calls).to.eql([[1], [2], [3]])
+ });
+ it('should return a Promise: mapSeries', async () => {
+ expect (async.mapSeries.name).to.contain('mapSeries')
+ const calls = []
+ await async.mapSeries(inputObj, async (...args) => { calls.push(args) });
+ expect(calls).to.eql([[1], [2], [3]])
+ });
+ it('should return a Promise: mapLimit', async () => {
+ expect (async.mapLimit.name).to.contain('mapLimit')
+ const calls = []
+ await async.mapLimit(inputObj, 1, async (...args) => { calls.push(args) });
+ expect(calls).to.eql([[1], [2], [3]])
+ });
+
+ it('should return a Promise: mapValues', async () => {
+ expect (async.mapValues.name).to.contain('mapValues')
+ const calls = []
+ await async.mapValues(inputObj, async (...args) => { calls.push(args) });
+ expect(calls).to.eql([[1, 'a'], [2, 'b'], [3, 'c']])
+ });
+ it('should return a Promise: mapValuesSeries', async () => {
+ expect (async.mapValuesSeries.name).to.contain('mapValuesSeries')
+ const calls = []
+ await async.mapValuesSeries(inputObj, async (...args) => { calls.push(args) });
+ expect(calls).to.eql([[1, 'a'], [2, 'b'], [3, 'c']])
+ });
+ it('should return a Promise: mapValuesLimit', async () => {
+ expect (async.mapValuesLimit.name).to.contain('mapValuesLimit')
+ const calls = []
+ await async.mapValuesLimit(inputObj, 1, async (...args) => { calls.push(args) });
+ expect(calls).to.eql([[1, 'a'], [2, 'b'], [3, 'c']])
+ });
+
+
+ it('should return a Promise: reduce', async () => {
+ expect (async.reduce.name).to.contain('reduce')
+ const calls = []
+ await async.reduce(input, 1, async (...args) => calls.push(args));
+ expect(calls).to.eql([[1, 1], [1, 2], [2, 3]])
+ });
+ it('should return a Promise: reduceRight', async () => {
+ expect (async.reduceRight.name).to.contain('reduceRight')
+ const calls = []
+ await async.reduceRight(input, 1, async (...args) => calls.push(args));
+ expect(calls).to.eql([[1, 3], [1, 2], [2, 1]])
+ });
+
+ it('should return a Promise: reject', async () => {
+ expect (async.reject.name).to.contain('reject')
+ const calls = []
+ await async.reject(inputObj, async (...args) => { calls.push(args) });
+ expect(calls).to.eql([[1], [2], [3]])
+ });
+ it('should return a Promise: rejectSeries', async () => {
+ expect (async.rejectSeries.name).to.contain('rejectSeries')
+ const calls = []
+ await async.rejectSeries(inputObj, async (...args) => { calls.push(args) });
+ expect(calls).to.eql([[1], [2], [3]])
+ });
+ it('should return a Promise: rejectLimit', async () => {
+ expect (async.rejectLimit.name).to.contain('rejectLimit')
+ const calls = []
+ await async.rejectLimit(inputObj, 1, async (...args) => { calls.push(args) });
+ expect(calls).to.eql([[1], [2], [3]])
+ });
+
+ it('should return a Promise: some', async () => {
+ expect (async.some.name).to.contain('some')
+ const calls = []
+ await async.some(input, async (...args) => { calls.push(args); return args[0] === 3 });
+ expect(calls).to.eql([[1], [2], [3]])
+ });
+ it('should return a Promise: someSeries', async () => {
+ expect (async.someSeries.name).to.contain('someSeries')
+ const calls = []
+ await async.someSeries(input, async (...args) => { calls.push(args); return args[0] === 3 });
+ expect(calls).to.eql([[1], [2], [3]])
+ });
+ it('should return a Promise: someLimit', async () => {
+ expect (async.someLimit.name).to.contain('someLimit')
+ const calls = []
+ await async.someLimit(input, 1, async (...args) => { calls.push(args); return args[0] === 3 });
+ expect(calls).to.eql([[1], [2], [3]])
+ });
+
+ it('should return a Promise: sortBy', async () => {
+ expect (async.sortBy.name).to.contain('sortBy')
+ const calls = []
+ await async.sortBy(input, async (...args) => { calls.push(args) });
+ expect(calls).to.eql([[1], [2], [3]])
+ });
+
+ it('should return a Promise: times', async () => {
+ expect (async.times.name).to.contain('times')
+ const calls = []
+ await async.times(3, async (...args) => { calls.push(args); return args[0] === 3 });
+ expect(calls).to.eql([[0], [1], [2]])
+ });
+ it('should return a Promise: timesSeries', async () => {
+ expect (async.timesSeries.name).to.contain('timesSeries')
+ const calls = []
+ await async.timesSeries(3, async (...args) => { calls.push(args); return args[0] === 3 });
+ expect(calls).to.eql([[0], [1], [2]])
+ });
+ it('should return a Promise: timesLimit', async () => {
+ expect (async.timesLimit.name).to.contain('timesLimit')
+ const calls = []
+ await async.timesLimit(3, 1, async (...args) => { calls.push(args); return args[0] === 3 });
+ expect(calls).to.eql([[0], [1], [2]])
+ });
+
+ it('should return a Promise: transform', async () => {
+ expect (async.transform.name).to.contain('transform')
+ const calls = []
+ await async.transform(inputObj, 1, async (...args) => calls.push(args));
+ expect(calls).to.eql([[1, 1, 'a'], [1, 2, 'b'], [1, 3, 'c']])
+ });
+ it('should return a Promise: transform (2 args)', async () => {
+ expect (async.transform.name).to.contain('transform')
+ const calls = []
+ await async.transform(inputObj, async (...args) => calls.push(args));
+ expect(calls).to.eql([[{}, 1, 'a'], [{}, 2, 'b'], [{}, 3, 'c']])
+ });
+
+ /*
+ * Control flow
+ */
+
+ // TODO: figure out to do with applyEach
+
+ it('should return a Promise: auto', async () => {
+ expect (async.auto.name).to.contain('auto')
+ const calls = []
+ await async.auto({
+ async a () {
+ calls.push('a')
+ return Promise.resolve('a')
+ },
+ b: ['a', 'c', async () => calls.push('b')],
+ async c () {
+ await Promise.resolve()
+ calls.push('c')
+ return Promise.resolve('c')
+ }
+ });
+ expect(calls).to.eql(['a', 'c', 'b'])
+ });
+ it('should return a Promise: autoInject', async () => {
+ expect (async.autoInject.name).to.contain('autoInject')
+ const calls = []
+ await async.autoInject({
+ async a () {
+ calls.push('a')
+ return 'a'
+ },
+ async b(a, c) { calls.push('b'); calls.push(a, c) },
+ async c () {
+ calls.push('c')
+ return 'c'
+ }
+ }, 1);
+ expect(calls).to.eql(['a', 'c', 'b', 'a', 'c'])
+ });
+
+ it('should return a Promise: compose', async () => {
+ expect (async.compose.name).to.contain('compose')
+ const calls = []
+ const fn = async.compose(
+ async (...args) => calls.push('a', args),
+ async (...args) => calls.push('b', args)
+ );
+ const result = await fn(1, 2)
+ expect(calls).to.eql(['b', [1, 2], 'a', [2]])
+ expect(result).to.eql(4)
+ });
+ it('should return a Promise: seq', async () => {
+ expect (async.seq.name).to.contain('seq')
+ const calls = []
+ const fn = async.seq(
+ async (...args) => calls.push('a', args),
+ async (...args) => calls.push('b', args)
+ );
+ const result = await fn(1, 2)
+ expect(calls).to.eql(['a', [1, 2], 'b', [2]])
+ expect(result).to.eql(4)
+ });
+
+ it('should return a Promise: whilst', async () => {
+ expect (async.whilst.name).to.contain('whilst')
+ const calls = []
+ let counter = 0
+ await async.whilst(
+ async () => {calls.push('test', counter); return counter < 5},
+ async () => { calls.push('fn'); counter++ }
+ );
+ expect(calls).to.eql([
+ 'test', 0, 'fn',
+ 'test', 1, 'fn',
+ 'test', 2, 'fn',
+ 'test', 3, 'fn',
+ 'test', 4, 'fn',
+ 'test', 5
+ ])
+ });
+ it('should return a Promise: until', async () => {
+ expect (async.until.name).to.contain('until')
+ const calls = []
+ let counter = 0
+ await async.until(
+ async () => {calls.push('test', counter); return counter === 5},
+ async () => { calls.push('fn'); counter++ }
+ );
+ expect(calls).to.eql([
+ 'test', 0, 'fn',
+ 'test', 1, 'fn',
+ 'test', 2, 'fn',
+ 'test', 3, 'fn',
+ 'test', 4, 'fn',
+ 'test', 5
+ ])
+ });
+ it('should return a Promise: doWhilst', async () => {
+ expect (async.doWhilst.name).to.contain('doWhilst')
+ const calls = []
+ let counter = 0
+ await async.doWhilst(
+ async () => { calls.push('fn'); counter++ },
+ async () => {calls.push('test', counter); return counter < 5}
+ );
+ expect(calls).to.eql([
+ 'fn',
+ 'test', 1, 'fn',
+ 'test', 2, 'fn',
+ 'test', 3, 'fn',
+ 'test', 4, 'fn',
+ 'test', 5
+ ])
+ });
+ it('should return a Promise: doUntil', async () => {
+ expect (async.doUntil.name).to.contain('doUntil')
+ const calls = []
+ let counter = 0
+ await async.doUntil(
+ async () => { calls.push('fn'); counter++ },
+ async () => {calls.push('test', counter); return counter === 5}
+ );
+ expect(calls).to.eql([
+ 'fn',
+ 'test', 1, 'fn',
+ 'test', 2, 'fn',
+ 'test', 3, 'fn',
+ 'test', 4, 'fn',
+ 'test', 5
+ ])
+ });
+
+ it('should return a Promise: forever', async () => {
+ expect (async.forever.name).to.contain('forever')
+ const calls = []
+ let counter = 0
+ try {
+ await async.forever(async () => {
+ calls.push(counter)
+ counter++
+ await Promise.resolve()
+ if (counter === 5) throw new Error()
+ })
+ } catch (e) {
+ var err = e
+ }
+ expect(calls).to.eql([0, 1, 2, 3, 4])
+ expect(err).to.be.an('error')
+ });
+
+ it('should return a Promise: parallel', async () => {
+ expect (async.parallel.name).to.contain('parallel')
+ const calls = []
+ await async.parallel([
+ async () => { await Promise.resolve(); calls.push(1) },
+ async () => { await Promise.resolve(); calls.push(1) },
+ async () => { await Promise.resolve(); calls.push(1) },
+ async () => { await Promise.resolve(); calls.push(1) },
+ ])
+ expect(calls).to.eql([1, 1, 1, 1])
+ });
+ it('should return a Promise: parallelLimit', async () => {
+ expect (async.parallelLimit.name).to.contain('parallelLimit')
+ const calls = []
+ await async.parallelLimit([
+ async () => { await Promise.resolve(); calls.push(1) },
+ async () => { await Promise.resolve(); calls.push(1) },
+ async () => { await Promise.resolve(); calls.push(1) },
+ async () => { await Promise.resolve(); calls.push(1) },
+ ], 2)
+ expect(calls).to.eql([1, 1, 1, 1])
+ });
+ it('should return a Promise: series', async () => {
+ expect (async.series.name).to.contain('series')
+ const calls = []
+ await async.series([
+ async () => { await Promise.resolve(); calls.push(1) },
+ async () => { await Promise.resolve(); calls.push(1) },
+ async () => { await Promise.resolve(); calls.push(1) },
+ async () => { await Promise.resolve(); calls.push(1) },
+ ], 2)
+ expect(calls).to.eql([1, 1, 1, 1])
+ });
+
+ it('should return a Promise: race', async () => {
+ expect (async.race.name).to.contain('race')
+ const calls = []
+ await async.race([
+ async () => { await Promise.resolve(); calls.push(1) },
+ async () => { await Promise.resolve(); calls.push(1) },
+ async () => { await Promise.resolve(); calls.push(1) },
+ async () => { await Promise.resolve(); calls.push(1) },
+ ], 2)
+ expect(calls).to.eql([1, 1, 1, 1])
+ });
+
+ it('should return a Promise: retryable', async () => {
+ expect (async.retryable.name).to.contain('retryable')
+ let counter = 0
+ const calls = []
+ const fn = async.retryable(async (a, b) => {
+ calls.push(a, b)
+ counter++
+ if (counter < 3) throw new Error()
+ })
+ const promise = fn(1, 2)
+ expect(promise.then).to.be.a('function')
+ await promise
+ expect(calls).to.eql([1, 2, 1, 2, 1, 2])
+ });
+ it('should return a Promise: retryable (arity 0)', async () => {
+ expect (async.retryable.name).to.contain('retryable')
+ let counter = 0
+ const calls = []
+ const fn = async.retryable({times: 5}, async () => {
+ calls.push(0)
+ counter++
+ if (counter < 3) throw new Error()
+ })
+ await fn()
+ expect(calls).to.eql([0, 0, 0])
+ });
+
+ it('should return a Promise: retry', async () => {
+ expect (async.retry.name).to.contain('retry')
+ let counter = 0
+ const calls = []
+ await async.retry(async () => {
+ calls.push(counter)
+ counter++
+ if (counter < 3) throw new Error()
+ })
+ expect(calls).to.eql([0, 1, 2])
+ });
+
+ it('should return a Promise: tryEach', async () => {
+ expect (async.tryEach.name).to.contain('tryEach')
+ const calls = []
+ await async.tryEach([
+ async () => { await Promise.resolve(); calls.push(1); throw new Error() },
+ async () => { await Promise.resolve(); calls.push(2); throw new Error() },
+ async () => { await Promise.resolve(); calls.push(3) },
+ async () => { await Promise.resolve(); calls.push(4) },
+ ], 2)
+ expect(calls).to.eql([1, 2, 3])
+ });
+
+ it('should return a Promise: waterfall', async () => {
+ expect (async.waterfall.name).to.contain('waterfall')
+ const calls = []
+ await async.waterfall([
+ async () => { await Promise.resolve(); calls.push(1) },
+ async () => { await Promise.resolve(); calls.push(2) },
+ async () => { await Promise.resolve(); calls.push(3) },
+ async () => { await Promise.resolve(); calls.push(4) },
+ ], 2)
+ expect(calls).to.eql([1, 2, 3, 4])
+ });
+
+ /*
+ * Util
+ */
+
+
+};
diff --git a/test/retry.js b/test/retry.js
index 7369f8a..e7bc36a 100644
--- a/test/retry.js
+++ b/test/retry.js
@@ -115,7 +115,7 @@ describe("retry", () => {
async.retry((cb) => {
calls++;
cb("fail");
- });
+ }).catch(() => {});
setTimeout(() => {
expect(calls).to.equal(5);
done();