From c99007ffc0c58ac9a7c3197009edf10cf6df56c9 Mon Sep 17 00:00:00 2001 From: zoubin Date: Tue, 13 Oct 2015 10:16:29 +0800 Subject: [PATCH] forEach, in sequence; map, in parallel --- README.md | 69 +++++++++++++++++++++++++++---------- example/forEach.js | 17 +++++++++ index.js | 3 +- lib/{each.js => forEach.js} | 6 +++- lib/map.js | 21 +++++++++-- lib/reduce.js | 1 - test/forEach.js | 42 ++++++++++++++++++++++ 7 files changed, 135 insertions(+), 24 deletions(-) create mode 100644 example/forEach.js rename lib/{each.js => forEach.js} (65%) create mode 100644 test/forEach.js diff --git a/README.md b/README.md index 9545bb1..f45bc6d 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,7 @@ Methods: - [filter](#filter) - [map](#map) +- [forEach](#forEach) - [reduce](#reduce) - [chain](#chain) @@ -35,18 +36,22 @@ filter( function (v) { return new Promise(function (rs) { process.nextTick(function () { - rs(v % 2); - }); - }); + rs(v % 2) + }) + }) }, function (err, results) { - console.log('promise:', results); + console.log('promise:', results) } -); +) ``` ## map +`fn` is called with elements in parallel. +If you want to run `fn` in sequence, +use [forEach](#forEach) instead. + Signature: `map(arr, fn, done)` ```javascript @@ -54,13 +59,39 @@ map( [1, 2, 3, 4], function (v, i, a, next) { process.nextTick(function () { - next(null, v << 2); - }); + next(null, v << 2) + }) }, function (err, results) { - console.log('async:', results); + console.log('async:', results) } -); +) + +``` + +## forEach + +`fn` is called with elements in sequence. +If you want to run `fn` in parallel, +use [map](#map) instead. + +Signature: `forEach(arr, fn, done)` + +```javascript +var count = 0 + +forEach( + [1, 2, 3, 4], + function (v, i, _, next) { + process.nextTick(function () { + console.log(count++ === i) + next(null, v << 2) + }) + }, + function (err, results) { + console.log(results) + } +) ``` @@ -73,13 +104,13 @@ reduce( [1, 2, 3, 4], function (a, b, i, arr, next) { process.nextTick(function () { - next(null, a + b); - }); + next(null, a + b) + }) }, function (err, results) { - console.log('async:', results); + console.log('async:', results) } -); +) ``` @@ -123,21 +154,21 @@ methods.chain( ) function odd(v) { - return v % 2; + return v % 2 } function plusplus(v, i, a, next) { process.nextTick(function () { - next(null, ++v); - }); + next(null, ++v) + }) } function sum(a, b) { return new Promise(function (rs) { process.nextTick(function () { - rs(a + b); - }); - }); + rs(a + b) + }) + }) } ``` diff --git a/example/forEach.js b/example/forEach.js new file mode 100644 index 0000000..c13e555 --- /dev/null +++ b/example/forEach.js @@ -0,0 +1,17 @@ +var forEach = require('..').forEach + +var count = 0 + +forEach( + [1, 2, 3, 4], + function (v, i, _, next) { + process.nextTick(function () { + console.log(count++ === i) + next(null, v << 2) + }) + }, + function (err, results) { + console.log(results) + } +) + diff --git a/index.js b/index.js index b36f7b8..5608f1d 100644 --- a/index.js +++ b/index.js @@ -1,5 +1,6 @@ -exports.forEach = exports.map = require('./lib/map') +exports.forEach = require('./lib/forEach') +exports.map = require('./lib/map') exports.filter = require('./lib/filter') exports.reduce = require('./lib/reduce') exports.chain = require('./lib/chain') diff --git a/lib/each.js b/lib/forEach.js similarity index 65% rename from lib/each.js rename to lib/forEach.js index df235a3..00ffe53 100644 --- a/lib/each.js +++ b/lib/forEach.js @@ -1,6 +1,10 @@ var run = require('run-callback') -module.exports = function each(arr, fn, start, end, res, done) { +module.exports = function (arr, fn, done) { + each(arr, fn, 0, arr.length, [], done) +} + +function each(arr, fn, start, end, res, done) { if (end <= start) { return done(null, res) } diff --git a/lib/map.js b/lib/map.js index c65e395..74dbec9 100644 --- a/lib/map.js +++ b/lib/map.js @@ -1,6 +1,23 @@ -var each = require('./each') +var run = require('run-callback') module.exports = function (arr, fn, done) { - each(arr, fn, 0, arr.length, [], done) + var pending = arr.length + var results = [] + var errored = false + arr.forEach(function (v, i) { + run([fn, v, i, arr], function (err, r) { + if (errored) { + return + } + if (err) { + errored = true + return done(err) + } + results[i] = r + if (--pending === 0) { + done(null, results) + } + }) + }) } diff --git a/lib/reduce.js b/lib/reduce.js index bb333a4..e1edf65 100644 --- a/lib/reduce.js +++ b/lib/reduce.js @@ -30,4 +30,3 @@ module.exports = function (arr, fn, initial, done) { }(start)) } - diff --git a/test/forEach.js b/test/forEach.js new file mode 100644 index 0000000..b73771d --- /dev/null +++ b/test/forEach.js @@ -0,0 +1,42 @@ +var test = require('tape') +var each = require('..').forEach + +test('forEach', function(t, cb) { + var count = 0 + each( + [1, 2, 3, 4], + function (v, i, a, next) { + process.nextTick(function () { + t.equal(count++, i) + next(null, v << 2) + }) + }, + function (err, results) { + t.same(results, [4, 8, 12, 16]) + cb() + } + ) + +}) + +test('forEach, err', function(t) { + t.plan(1) + each( + ['1', 2, '3', 4], + function (v, i, a, next) { + process.nextTick(function () { + try { + var code = v.charCodeAt(0) + } catch (e) { + return next(e) + } + next(null, code) + }) + }, + function (err) { + t.ok(err instanceof Error) + } + ) + +}) +