diff --git a/lib/doDuring.js b/lib/doDuring.js deleted file mode 100644 index be078d579..000000000 --- a/lib/doDuring.js +++ /dev/null @@ -1,46 +0,0 @@ -import noop from './internal/noop'; -import onlyOnce from './internal/onlyOnce'; -import wrapAsync from './internal/wrapAsync'; - -/** - * The post-check version of [`during`]{@link module:ControlFlow.during}. To reflect the difference in - * the order of operations, the arguments `test` and `fn` are switched. - * - * Also a version of [`doWhilst`]{@link module:ControlFlow.doWhilst} with asynchronous `test` function. - * @name doDuring - * @static - * @memberOf module:ControlFlow - * @method - * @see [async.during]{@link module:ControlFlow.during} - * @category Control Flow - * @param {AsyncFunction} fn - An async function which is called each time - * `test` passes. Invoked with (callback). - * @param {AsyncFunction} test - asynchronous truth test to perform before each - * execution of `fn`. Invoked with (...args, callback), where `...args` are the - * non-error args from the previous callback of `fn`. - * @param {Function} [callback] - A callback which is called after the test - * function has failed and repeated execution of `fn` has stopped. `callback` - * will be passed an error if one occurred, otherwise `null`. - */ -export default function doDuring(fn, test, callback) { - callback = onlyOnce(callback || noop); - var _fn = wrapAsync(fn); - var _test = wrapAsync(test); - - function next(err, ...args) { - if (err) return callback(err); - if (err === false) return; - _test(...args, check); - } - - function check(err, truth) { - if (err) return callback(err); - if (err === false) return; - if (!truth) return callback(null); - _fn(next); - } - - check(null, true); - -} - diff --git a/lib/doUntil.js b/lib/doUntil.js index aa7d323b2..8becfa0f3 100644 --- a/lib/doUntil.js +++ b/lib/doUntil.js @@ -1,4 +1,5 @@ import doWhilst from './doWhilst'; +import wrapAsync from './internal/wrapAsync'; /** * Like ['doWhilst']{@link module:ControlFlow.doWhilst}, except the `test` is inverted. Note the @@ -12,14 +13,18 @@ import doWhilst from './doWhilst'; * @category Control Flow * @param {AsyncFunction} iteratee - An async function which is called each time * `test` fails. Invoked with (callback). - * @param {Function} test - synchronous truth test to perform after each - * execution of `iteratee`. Invoked with any non-error callback results of - * `iteratee`. + * @param {Function} test - asynchronous truth test to perform after each + * execution of `iteratee`. Invoked with (...args, callback), where `...args` are the + * non-error args from the previous callback of `fn` * @param {Function} [callback] - A callback which is called after the test * 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]); */ export default function doUntil(iteratee, test, callback) { - doWhilst(iteratee, (...args) => !test(...args), callback); + const _test = wrapAsync(test) + 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 324d2e087..5a63425e2 100644 --- a/lib/doWhilst.js +++ b/lib/doWhilst.js @@ -17,22 +17,34 @@ import wrapAsync from './internal/wrapAsync'; * @category Control Flow * @param {AsyncFunction} iteratee - A function which is called each time `test` * passes. Invoked with (callback). - * @param {Function} test - synchronous truth test to perform after each - * execution of `iteratee`. Invoked with any non-error callback results of - * `iteratee`. + * @param {Function} test - asynchronous truth test to perform after each + * execution of `iteratee`. Invoked with (...args, callback), where `...args` are the + * non-error args from the previous callback of `fn`. * @param {Function} [callback] - A callback which is called after the test * 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 */ export default function doWhilst(iteratee, test, callback) { callback = onlyOnce(callback || noop); - var _iteratee = wrapAsync(iteratee); - function next (err, ...args) { + var _fn = wrapAsync(iteratee); + var _test = wrapAsync(test); + var results + + function next(err, ...args) { + if (err) return callback(err); + if (err === false) return; + results = args + _test(...args, check); + } + + function check(err, truth) { if (err) return callback(err); if (err === false) return; - if (test(...args)) return _iteratee(next); - callback(null, ...args); + if (!truth) return callback(null, ...results); + _fn(next); } - _iteratee(next); + + return check(null, true); } diff --git a/lib/during.js b/lib/during.js deleted file mode 100644 index 02da045a2..000000000 --- a/lib/during.js +++ /dev/null @@ -1,60 +0,0 @@ -import noop from './internal/noop'; -import onlyOnce from './internal/onlyOnce'; -import wrapAsync from './internal/wrapAsync'; - -/** - * Like [`whilst`]{@link module:ControlFlow.whilst}, except the `test` is an asynchronous function that - * is passed a callback in the form of `function (err, truth)`. If error is - * passed to `test` or `fn`, the main callback is immediately called with the - * value of the error. - * - * @name during - * @static - * @memberOf module:ControlFlow - * @method - * @see [async.whilst]{@link module:ControlFlow.whilst} - * @category Control Flow - * @param {AsyncFunction} test - asynchronous truth test to perform before each - * execution of `fn`. Invoked with (callback). - * @param {AsyncFunction} fn - An async function which is called each time - * `test` passes. Invoked with (callback). - * @param {Function} [callback] - A callback which is called after the test - * function has failed and repeated execution of `fn` has stopped. `callback` - * will be passed an error, if one occurred, otherwise `null`. - * @example - * - * var count = 0; - * - * async.during( - * function (callback) { - * return callback(null, count < 5); - * }, - * function (callback) { - * count++; - * setTimeout(callback, 1000); - * }, - * function (err) { - * // 5 seconds have passed - * } - * ); - */ -export default function during(test, fn, callback) { - callback = onlyOnce(callback || noop); - var _fn = wrapAsync(fn); - var _test = wrapAsync(test); - - function next(err) { - if (err) return callback(err); - if (err === false) return; - _test(check); - } - - function check(err, truth) { - if (err) return callback(err); - if (err === false) return; - if (!truth) return callback(null); - _fn(next); - } - - _test(check); -} diff --git a/lib/index.js b/lib/index.js index 0eee7bda8..e0ddc686e 100644 --- a/lib/index.js +++ b/lib/index.js @@ -79,10 +79,8 @@ import detect from './detect' import detectLimit from './detectLimit' import detectSeries from './detectSeries' import dir from './dir' -import doDuring from './doDuring' import doUntil from './doUntil' import doWhilst from './doWhilst' -import during from './during' import each from './each' import eachLimit from './eachLimit' import eachOf from './eachOf' @@ -158,10 +156,8 @@ export default { detectLimit, detectSeries, dir, - doDuring, doUntil, doWhilst, - during, each, eachLimit, eachOf, @@ -262,10 +258,8 @@ export { detectLimit as detectLimit, detectSeries as detectSeries, dir as dir, - doDuring as doDuring, doUntil as doUntil, doWhilst as doWhilst, - during as during, each as each, eachLimit as eachLimit, eachOf as eachOf, diff --git a/lib/until.js b/lib/until.js index 31b7e9f24..16f1263bf 100644 --- a/lib/until.js +++ b/lib/until.js @@ -1,4 +1,5 @@ import whilst from './whilst'; +import wrapAsync from './internal/wrapAsync'; /** * Repeatedly call `iteratee` until `test` returns `true`. Calls `callback` when @@ -13,15 +14,30 @@ import whilst from './whilst'; * @method * @see [async.whilst]{@link module:ControlFlow.whilst} * @category Control Flow - * @param {Function} test - synchronous truth test to perform before each - * execution of `iteratee`. Invoked with (). + * @param {Function} test - asynchronous truth test to perform before each + * execution of `iteratee`. Invoked with (callbac). * @param {AsyncFunction} iteratee - An async function which is called each time * `test` fails. Invoked with (callback). * @param {Function} [callback] - A callback which is called after the test * 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]); + * + * @example + * const results = [] + * async.until(function iter(next) { + * fetchPage(url, (err, body) => { + * if (err) return next(err) + * results = results.concat(body.objects) + * next(err, body) + * }) + * }, function test(page, cb) { + * cb(null, page.next == null) + * }, function done (err) { + * // all pages have been fetched + * }) */ export default function until(test, iteratee, callback) { - whilst((...args) => !test(...args), iteratee, callback); + const _test = wrapAsync(test) + whilst((cb) => _test((err, truth) => cb (err, !truth)), iteratee, callback); } diff --git a/lib/whilst.js b/lib/whilst.js index 23dc7c905..d42e6a798 100644 --- a/lib/whilst.js +++ b/lib/whilst.js @@ -12,7 +12,7 @@ import wrapAsync from './internal/wrapAsync'; * @memberOf module:ControlFlow * @method * @category Control Flow - * @param {Function} test - synchronous truth test to perform before each + * @param {AsyncFunction} test - asynchronous truth test to perform before each * execution of `iteratee`. Invoked with (). * @param {AsyncFunction} iteratee - An async function which is called each time * `test` passes. Invoked with (callback). @@ -25,8 +25,8 @@ import wrapAsync from './internal/wrapAsync'; * * var count = 0; * async.whilst( - * function() { return count < 5; }, - * function(callback) { + * function test(cb) { cb(null, count < 5;) }, + * function iter(callback) { * count++; * setTimeout(function() { * callback(null, count); @@ -39,13 +39,23 @@ import wrapAsync from './internal/wrapAsync'; */ export default function whilst(test, iteratee, callback) { callback = onlyOnce(callback || noop); - var _iteratee = wrapAsync(iteratee); - if (!test()) return callback(null); - var next = (err, ...args) => { + var _fn = wrapAsync(iteratee); + var _test = wrapAsync(test); + var results + + function next(err, ...rest) { if (err) return callback(err); + results = rest; if (err === false) return; - if (test()) return _iteratee(next); - callback(null, ...args); - }; - _iteratee(next); + _test(check); + } + + function check(err, truth) { + if (err) return callback(err); + if (err === false) return; + if (!truth) return callback(null, ...results); + _fn(next); + } + + return _test(check); } diff --git a/test/during.js b/test/during.js deleted file mode 100644 index 60b58edfa..000000000 --- a/test/during.js +++ /dev/null @@ -1,146 +0,0 @@ -var async = require('../lib'); -var {expect} = require('chai'); -var assert = require('assert'); - -describe('during', () => { - - it('during', (done) => { - var call_order = []; - - var count = 0; - async.during( - (cb) => { - call_order.push(['test', count]); - cb(null, count < 5); - }, - (cb) => { - call_order.push(['iteratee', count]); - count++; - cb(null, count); - }, - (err) => { - assert(err === null, err + " passed instead of 'null'"); - expect(call_order).to.eql([ - ['test', 0], - ['iteratee', 0], ['test', 1], - ['iteratee', 1], ['test', 2], - ['iteratee', 2], ['test', 3], - ['iteratee', 3], ['test', 4], - ['iteratee', 4], ['test', 5], - ]); - expect(count).to.equal(5); - done(); - } - ); - }); - - it('during canceling', (done) => { - let counter = 0; - async.during( - cb => cb(null, true), - cb => { - counter++ - cb(counter === 2 ? false : null); - }, - () => { throw new Error('should not get here')} - ); - setTimeout(() => { - expect(counter).to.equal(2); - done(); - }, 10) - }) - - it('doDuring', (done) => { - var call_order = []; - - var count = 0; - async.doDuring( - (cb) => { - call_order.push(['iteratee', count]); - count++; - cb(null, count); - }, - (c, cb) => { - expect(c).to.equal(count); - call_order.push(['test', count]); - cb(null, count < 5); - }, - (err) => { - assert(err === null, err + " passed instead of 'null'"); - expect(call_order).to.eql([ - ['iteratee', 0], ['test', 1], - ['iteratee', 1], ['test', 2], - ['iteratee', 2], ['test', 3], - ['iteratee', 3], ['test', 4], - ['iteratee', 4], ['test', 5], - ]); - expect(count).to.equal(5); - done(); - } - ); - }); - - it('doDuring - error test', (done) => { - var error = new Error('asdas'); - - async.doDuring( - (cb) => { - cb(error); - }, - () => {}, - (err) => { - expect(err).to.equal(error); - done(); - } - ); - }); - - it('doDuring - error iteratee', (done) => { - var error = new Error('asdas'); - - async.doDuring( - (cb) => { - cb(null); - }, - (cb) => { - cb(error); - }, - (err) => { - expect(err).to.equal(error); - done(); - } - ); - }); - - it('doDuring canceling', (done) => { - let counter = 0; - async.doDuring( - cb => { - counter++ - cb(counter === 2 ? false : null); - }, - cb => cb(null, true), - () => { throw new Error('should not get here')} - ); - setTimeout(() => { - expect(counter).to.equal(2); - done(); - }, 10) - }) - - it('doDuring canceling in test', (done) => { - let counter = 0; - async.doDuring( - cb => { - counter++ - cb(null, counter); - }, - (n, cb) => cb(n === 2 ? false : null, true), - () => { throw new Error('should not get here')} - ); - setTimeout(() => { - expect(counter).to.equal(2); - done(); - }, 10) - }) -}); diff --git a/test/es2017/asyncFunctions.js b/test/es2017/asyncFunctions.js index 22468f815..680725bb7 100644 --- a/test/es2017/asyncFunctions.js +++ b/test/es2017/asyncFunctions.js @@ -412,31 +412,9 @@ module.exports = function () { }); }); - it('should handle async functions in during', (done) => { - var val = 0; - async.during(async () => { - return val < 3; - }, - async () => { - val += 1; - return val; - }, done); - }); - - it('should handle async functions in doDuring', (done) => { - var val = 0; - async.doDuring(async () => { - val += 1; - return val; - }, - async (res) => { - return res < 3; - }, done); - }); - it('should handle async functions in whilst', (done) => { var val = 0; - async.whilst(() => val < 3, + async.whilst(async () => val < 3, async () => { val += 1; return val; @@ -448,12 +426,12 @@ module.exports = function () { async.doWhilst(async () => { val += 1; return val; - }, (res) => res < 3, done); + }, async (res) => res < 3, done); }); it('should handle async functions in until', (done) => { var val = 0; - async.until(() => val > 3, + async.until(async () => val > 3, async () => { val += 1; return val; @@ -465,7 +443,7 @@ module.exports = function () { async.doUntil(async () => { val += 1; return val; - }, (res) => res > 3, done); + }, async (res) => res > 3, done); }); it('should handle async functions in forever', (done) => { diff --git a/test/until.js b/test/until.js index ea39945f8..cb478d793 100644 --- a/test/until.js +++ b/test/until.js @@ -7,10 +7,10 @@ describe('until', () => { var call_order = []; var count = 0; async.until( - (c) => { - expect(c).to.equal(undefined); + (cb) => { + expect(cb).to.be.a('function'); call_order.push(['test', count]); - return (count == 5); + return cb(null, count == 5); }, (cb) => { call_order.push(['iteratee', count]); @@ -37,7 +37,7 @@ describe('until', () => { it('until canceling', (done) => { let counter = 0; async.until( - () => false, + (cb) => cb(null, false), cb => { counter++ cb(counter === 2 ? false: null); @@ -59,10 +59,10 @@ describe('until', () => { count++; cb(null, count); }, - (c) => { + (c, cb) => { expect(c).to.equal(count); call_order.push(['test', count]); - return (count == 5); + return cb(null, count == 5); }, (err, result) => { assert(err === null, err + " passed instead of 'null'"); @@ -89,9 +89,9 @@ describe('until', () => { count++; cb(null, count); }, - (c) => { + (c, cb) => { call_order.push(['test', c]); - return (c == 5); + return cb(null, c == 5); }, (err, result) => { if (err) throw err; @@ -116,7 +116,7 @@ describe('until', () => { counter++ cb(counter === 2 ? false: null); }, - () => false, + (cb) => cb(null, false), () => { throw new Error('should not get here')} ); setTimeout(() => { diff --git a/test/whilst.js b/test/whilst.js index 8348504ea..1c222c9ac 100644 --- a/test/whilst.js +++ b/test/whilst.js @@ -8,10 +8,10 @@ describe('whilst', () => { var count = 0; async.whilst( - (c) => { - expect(c).to.equal(undefined); + (cb) => { + expect(cb).to.be.a('function'); call_order.push(['test', count]); - return (count < 5); + return cb(null, count < 5); }, (cb) => { call_order.push(['iteratee', count]); @@ -38,7 +38,7 @@ describe('whilst', () => { it('whilst optional callback', (done) => { var counter = 0; async.whilst( - () => { return counter < 2; }, + (cb) => cb(null, counter < 2), (cb) => { counter++; cb(); @@ -51,7 +51,7 @@ describe('whilst', () => { it('whilst canceling', (done) => { var counter = 0; async.whilst( - () => { return counter < 3; }, + (cb) => cb(null, counter < 3), (cb) => { counter++; cb(counter === 2 ? false : null); @@ -74,10 +74,10 @@ describe('whilst', () => { count++; cb(null, count); }, - (c) => { + (c, cb) => { expect(c).to.equal(count); call_order.push(['test', count]); - return (count < 5); + return cb(null, count < 5); }, (err, result) => { assert(err === null, err + " passed instead of 'null'"); @@ -104,9 +104,9 @@ describe('whilst', () => { count++; cb(null, count); }, - (c) => { + (c, cb) => { call_order.push(['test', c]); - return (c < 5); + return cb(null, c < 5); }, (err, result) => { if (err) throw err; @@ -146,7 +146,7 @@ describe('whilst', () => { counter++ cb(counter === 2 ? false : null); }, - () => true, + (cb) => cb(null, true), () => { throw new Error('should not get here')} ); setTimeout(() => {