+77
-7
@@ -13,4 +13,10 @@ /** | ||
| M = {}, // define the module | ||
| moduleName = 'asyncexit'; // the name of the module | ||
| moduleName = 'asynccond'; // the name of the module | ||
| var _isArray = Array.isArray || function (obj) { | ||
| return _toString.call(obj) === '[object Array]'; | ||
| }; | ||
| function noop (){}; | ||
| function _toArray(obj) { | ||
@@ -22,4 +28,6 @@ var res = { | ||
| for (var key in obj) { | ||
| res.keys.push(key); | ||
| res.vals.push(obj[key]); | ||
| if (obj.hasOwnProperty(key)) { | ||
| res.keys.push(key); | ||
| res.vals.push(obj[key]); | ||
| } | ||
| } | ||
@@ -44,2 +52,62 @@ return res; | ||
| /** | ||
| * Applies the function `iterator` to each item in `arr` in series. | ||
| * The `iterator` is called with an item from `arr`, and a callback | ||
| * when it has finished. If the `iterator` passes an error to its | ||
| * callback, the main `callback` is immediately called with the error. | ||
| * | ||
| * If a condition is applied on the internal callback of `iterator`, | ||
| * it pre-exits the series. | ||
| * | ||
| * #### Example | ||
| * | ||
| * ````js | ||
| * eachSeries( | ||
| * [ 1, 2, 3, 4, 5 ], | ||
| * // iterator | ||
| * function (data, cb) { | ||
| * cb(null, data * 2, (data * 2 > 5)); // exits if condition is met | ||
| * }, | ||
| * // callback | ||
| * function(err, data){ | ||
| * //> data = [ 2, 4, 6 ]); | ||
| * } | ||
| * ); | ||
| * ```` | ||
| * | ||
| * | ||
| * @param {Array} arr - array of items which are passed to `iterator` | ||
| * @param {Function} iterator - `function(item, cb)` `cb` needs to be called inside `iterator` | ||
| * @param {Function} [callback] - is of type `function(err, result)` and called after running the series | ||
| */ | ||
| function eachSeries(arr, iterator, callback) { | ||
| var i = 0, | ||
| results = []; | ||
| callback = callback || noop; | ||
| function cb(err, res, exit){ | ||
| results.push(res); | ||
| if (err || exit) { | ||
| return callback(err, results); | ||
| } | ||
| else { | ||
| run(); | ||
| } | ||
| } | ||
| function run() { | ||
| var a = arr[i++]; | ||
| if (a) { | ||
| iterator(a, cb); | ||
| } | ||
| else { | ||
| return callback(null, results); | ||
| } | ||
| } | ||
| run(); | ||
| } | ||
| M.eachSeries = eachSeries; | ||
| /** | ||
| * Run the functions in the `tasks` array in series, each one running | ||
@@ -83,3 +151,3 @@ * once the previous function has completed. If any functions in the | ||
| * @param {Array|Object} tasks - the async functions to run in series | ||
| * @param {Function} callback - is of type `function(err, result)` and called after running the series | ||
| * @param {Function} [callback] - is of type `function(err, result)` and called after running the series | ||
| */ | ||
@@ -91,3 +159,5 @@ function series(tasks, callback) { | ||
| if (!Array.isArray(tasks) && typeof(tasks) === 'object') { | ||
| callback = callback || noop; | ||
| if (!_isArray(tasks) && typeof(tasks) === 'object') { | ||
| keys = _toArray(tasks); | ||
@@ -175,3 +245,3 @@ tasks = keys.vals; | ||
| if (tasks.length === 1) { | ||
| if (Array.isArray(tasks[0])) { | ||
| if (_isArray(tasks[0])) { | ||
| tasks = tasks[0]; | ||
@@ -212,3 +282,3 @@ } | ||
| return function(data, _callback) { | ||
| callback = _callback; | ||
| callback = _callback || noop; | ||
| i = 0; | ||
@@ -215,0 +285,0 @@ run(null, data); |
+1
-0
@@ -21,1 +21,2 @@ The MIT License (MIT) | ||
| CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
+1
-1
| { | ||
| "name": "asynccond", | ||
| "version": "1.0.0", | ||
| "version": "1.1.0", | ||
| "description": "async series with conditional exit", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
+42
-2
@@ -8,7 +8,9 @@ # asynccond | ||
| Execute async functions in series with the ability to conditionally pre-exit the sequence. | ||
| Async series functions with the ability to conditionally pre-exit the sequence. | ||
| `seq` furthermore allows to trap errors within the sequence. | ||
| The functions provided are backwards compatible with [async][]. | ||
| ## Table of Contents | ||
@@ -19,2 +21,3 @@ | ||
| * [Description](#description) | ||
| * [eachSeries(arr, iterator, callback)](#eachseriesarr-iterator-callback) | ||
| * [series(tasks, callback)](#seriestasks-callback) | ||
@@ -30,2 +33,38 @@ * [seq(tasks)](#seqtasks) | ||
| ### eachSeries(arr, iterator, callback) | ||
| Applies the function `iterator` to each item in `arr` in series. | ||
| The `iterator` is called with an item from `arr`, and a callback | ||
| when it has finished. If the `iterator` passes an error to its | ||
| callback, the main `callback` is immediately called with the error. | ||
| If a condition is applied on the internal callback of `iterator`, | ||
| it pre-exits the series. | ||
| #### Example | ||
| ````js | ||
| eachSeries( | ||
| [ 1, 2, 3, 4, 5 ], | ||
| // iterator | ||
| function (data, cb) { | ||
| cb(null, data * 2, (data * 2 > 5)); // exits if condition is met | ||
| }, | ||
| // callback | ||
| function(err, data){ | ||
| //> data = [ 2, 4, 6 ]); | ||
| } | ||
| ); | ||
| ```` | ||
| **Parameters** | ||
| **arr**: `Array`, array of items which are passed to `iterator` | ||
| **iterator**: `function`, `function(item, cb)` `cb` needs to be called inside `iterator` | ||
| **callback**: `function`, is of type `function(err, result)` and called after running the series | ||
| ### series(tasks, callback) | ||
@@ -145,2 +184,3 @@ | ||
| * [async][async] | ||
| * [LICENSE][LICENSE] | ||
@@ -151,5 +191,5 @@ | ||
| [LICENSE]: ./LICENSE | ||
| [async]: https://github.com/caolan/async | ||
+61
-4
@@ -9,6 +9,7 @@ /** | ||
| var assert = require('assert'); | ||
| var seq = require('../index.js').seq; | ||
| var seq = require('../index.js').seq; | ||
| var series = require('../index.js').series; | ||
| var eachSeries = require('../index.js').eachSeries; | ||
| /* globals describe, it */ ///< used for jshint | ||
| /* globals describe, it */ | ||
@@ -31,2 +32,58 @@ // test helper | ||
| describe('#eachSeries', function(){ | ||
| it('can process an async function in series ', function(done){ | ||
| eachSeries([ 1, 2, 3, 4 ], | ||
| function (data, cb) { | ||
| process.nextTick(function(){ | ||
| cb(null, data * 2); | ||
| }); | ||
| }, | ||
| function(err, data){ | ||
| assert.ok(!err, ''+err); | ||
| assert.deepEqual(data, [ 2, 4, 6, 8 ]); | ||
| done(); | ||
| } | ||
| ); | ||
| }); | ||
| it('can exit on err', function(done){ | ||
| var i = 0; | ||
| eachSeries([ 1, 2, 3, 4 ], | ||
| function (data, cb) { | ||
| var err; | ||
| if (++i >= 2) { | ||
| err = 'err'; | ||
| } | ||
| process.nextTick(function(){ | ||
| cb(err, data * 2); | ||
| }); | ||
| }, | ||
| function(err, data){ | ||
| assert.ok(err, ''+err); | ||
| assert.deepEqual(data, [ 2, 4 ]); | ||
| done(); | ||
| } | ||
| ); | ||
| }); | ||
| it('can pre-exit on condition', function(done){ | ||
| eachSeries([ 1, 2, 3, 4 ], | ||
| function (data, cb) { | ||
| process.nextTick(function(){ | ||
| cb(null, data * 2, (data * 2 > 5)); | ||
| }); | ||
| }, | ||
| function(err, data){ | ||
| assert.ok(!err, ''+err); | ||
| assert.deepEqual(data, [ 2, 4, 6 ]); | ||
| done(); | ||
| } | ||
| ); | ||
| }); | ||
| }); | ||
| describe('#series', function(){ | ||
@@ -97,3 +154,3 @@ | ||
| it('can process async function in series with pre-exit', function(done){ | ||
| it('can pre-exit on condition', function(done){ | ||
| var data = 0 | ||
@@ -228,3 +285,3 @@ | ||
| it('can pre-exit', function(done){ | ||
| it('can pre-exit on condition', function(done){ | ||
| seq( | ||
@@ -231,0 +288,0 @@ step, |
19015
24.61%532
26.67%191
26.49%