diff --git a/README.md b/README.md index 7408659..60633df 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,7 @@ All methods return a promise. - [filter](#filter) - [map](#map) +- [series](#series) - [forEach](#foreach) - [reduce](#reduce) - [AsyncArray](#asyncarray) @@ -60,7 +61,7 @@ filter( Signature: `map(arr, fn, context)` -`fn` is called with elements in parallel. +`fn` is called with each element in parallel. ```javascript map( @@ -79,6 +80,38 @@ map( ``` +### series +This method works like `map`, +except that `fn` is called with each element in sequence rather than in parallel. + +Signature: `map(arr, fn, context)` + + +```javascript +var n = 1 +series( + [1, 2, 3, 4], + function (v, i, arr, next) { + var delay = rand() + console.log('i:', i, 'delay:', delay) + setTimeout(function() { + next(null, v << n++) + }, delay) + } +) +// i: 0 delay: 10 +// i: 1 delay: 50 +// i: 2 delay: 0 +// i: 3 delay: 80 +// [2, 8, 24, 64] +.then(log) + +function rand() { + return Math.floor(Math.random() * 10) * 10 +} + +``` + ### forEach `fn` is called with elements in sequence. @@ -125,6 +158,13 @@ reduce( ### AsyncArray Signature: `AsyncArray(arr)` +Methods: +* `map` +* `series` +* `filter` +* `forEach` +* `reduce` + ```javascript var origin = AsyncArray([1, 2, 3, 4, 5, 6]) var odd = origin.filter(isOdd) diff --git a/example/series.js b/example/series.js new file mode 100644 index 0000000..32862c6 --- /dev/null +++ b/example/series.js @@ -0,0 +1,21 @@ +var series = require('..').series + +var log = console.log.bind(console) + +var n = 1 +series( + [1, 2, 3, 4], + function (v, i, arr, next) { + var delay = rand() + console.log('i:', i, 'delay:', delay) + setTimeout(function() { + next(null, v << n++) + }, delay) + } +) +// [2, 8, 24, 64] +.then(log) + +function rand() { + return Math.floor(Math.random() * 10) * 10 +} diff --git a/index.js b/index.js index fe6dd82..c65952a 100644 --- a/index.js +++ b/index.js @@ -3,5 +3,6 @@ exports.forEach = require('./lib/forEach') exports.map = require('./lib/map') exports.filter = require('./lib/filter') exports.reduce = require('./lib/reduce') +exports.series = require('./lib/series') exports.Array = require('./lib/async-array') diff --git a/lib/async-array.js b/lib/async-array.js index cc342e5..4f2561f 100644 --- a/lib/async-array.js +++ b/lib/async-array.js @@ -1,5 +1,6 @@ var asyncMethods = { map: require('./map'), + series: require('./series'), filter: require('./filter'), reduce: require('./reduce'), forEach: require('./forEach'), @@ -12,7 +13,7 @@ function AsyncArray(arr) { this.result = Promise.resolve(arr || []) } -['map', 'filter', 'forEach', 'reduce'] +['map', 'filter', 'forEach', 'reduce', 'series'] .forEach(function (fnName) { AsyncArray.prototype[fnName] = function () { var args = slice(arguments) diff --git a/lib/series.js b/lib/series.js new file mode 100644 index 0000000..55f6c1b --- /dev/null +++ b/lib/series.js @@ -0,0 +1,18 @@ +var Runner = require('callback-sequence').Runner +var runner = Runner({ + run: { stream: false }, +}) + +module.exports = function (arr, fn, ctx) { + if (arguments.length < 3) { + ctx = arr + } + + return runner.series.apply(runner, arr.map(function (v, i) { + return fn.bind(ctx, v, i, arr) + })).then(function (results) { + return [].concat.apply([], results) + }) +} + + diff --git a/package.json b/package.json index 8dd851b..02660ad 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ }, "homepage": "https://github.com/zoubin/async-array-methods#readme", "dependencies": { - "callback-sequence": "^3.1.0" + "callback-sequence": "^3.2.0" }, "devDependencies": { "eslint": "^1.5.1", diff --git a/test/array.js b/test/array.js index 8317a0d..00dd198 100644 --- a/test/array.js +++ b/test/array.js @@ -22,6 +22,20 @@ test('map', function(t) { }) }) +test('series', function(t) { + var origin = AsyncArray([1, 3, 5]) + var delays = [10, 0, 20] + return origin.series(function (v, i, arr, next) { + setTimeout(function() { + next(null, v + 1) + }, delays[i]) + }) + .then(function (res) { + t.same(res, [2, 4, 6]) + }) + +}) + test('reduce', function(t) { var origin = AsyncArray([1, 3, 5]) return origin.reduce(function (a, b) { diff --git a/test/series.js b/test/series.js new file mode 100644 index 0000000..b160c18 --- /dev/null +++ b/test/series.js @@ -0,0 +1,34 @@ +var test = require('tap').test +var series = require('../lib/series') + +test('results', function(t) { + t.plan(2) + + var res = [] + series([30, 20, 10], function (v, i, arr, next) { + setTimeout(function() { + res.push(v) + next(null, i) + }, v) + }).then(function (results) { + t.same(results, [0, 1, 2]) + t.same(res, [30, 20, 10]) + }) +}) + +test('context', function(t) { + t.plan(2) + + var res = [] + series([30, 20, 10], function (v, i, arr, next) { + var self = this + setTimeout(function() { + res.push(v) + next(null, i + self.n) + }, v) + }, { n: 1 }).then(function (results) { + t.same(results, [1, 2, 3]) + t.same(res, [30, 20, 10]) + }) +}) +