Skip to content

Commit 16dfe42

Browse files
committed
Renamed forEach*
1 parent 15ff994 commit 16dfe42

File tree

8 files changed

+147
-239
lines changed

8 files changed

+147
-239
lines changed

modern-async.d.ts

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -92,18 +92,10 @@ declare module "findIndex" {
9292
function findIndex<V>(iterable: Iterable<V> | AsyncIterable<V>, iteratee: (value: V, index: number, iterable: Iterable<V> | AsyncIterable<V>) => Promise<boolean> | boolean, queueOrConcurrency: Queue | number, ordered?: boolean): Promise<number>;
9393
import Queue from "Queue";
9494
}
95-
declare module "forEachLimit" {
96-
export default forEachLimit;
97-
function forEachLimit<V>(iterable: Iterable<V> | AsyncIterable<V>, iteratee: (value: V, index: number, iterable: Iterable<V> | AsyncIterable<V>) => Promise<void> | void, queueOrConcurrency: Queue | number): Promise<void>;
98-
import Queue from "Queue";
99-
}
10095
declare module "forEach" {
10196
export default forEach;
102-
function forEach<V>(iterable: Iterable<V> | AsyncIterable<V>, iteratee: (value: V, index: number, iterable: Iterable<V> | AsyncIterable<V>) => Promise<void> | void): Promise<void>;
103-
}
104-
declare module "forEachSeries" {
105-
export default forEachSeries;
106-
function forEachSeries<V>(iterable: Iterable<V> | AsyncIterable<V>, iteratee: (value: V, index: number, iterable: Iterable<V> | AsyncIterable<V>) => Promise<void> | void): Promise<void>;
97+
function forEach<V>(iterable: Iterable<V> | AsyncIterable<V>, iteratee: (value: V, index: number, iterable: Iterable<V> | AsyncIterable<V>) => Promise<void> | void, queueOrConcurrency: Queue | number): Promise<void>;
98+
import Queue from "Queue";
10799
}
108100
declare module "mapLimit" {
109101
export default mapLimit;
@@ -207,8 +199,6 @@ declare module "modern-async" {
207199
export { default as find } from "find";
208200
export { default as findIndex } from "findIndex";
209201
export { default as forEach } from "forEach";
210-
export { default as forEachLimit } from "forEachLimit";
211-
export { default as forEachSeries } from "forEachSeries";
212202
export { default as map } from "map";
213203
export { default as mapGenerator } from "mapGenerator";
214204
export { default as mapLimit } from "mapLimit";

src/forEach.mjs

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,44 @@
11

2-
import forEachLimit from './forEachLimit.mjs'
2+
import mapGenerator from './mapGenerator.mjs'
3+
import Queue from './Queue.mjs'
34

45
/**
56
* Calls a function on each element of iterable.
67
*
7-
* Multiple calls to `iteratee` will be performed in parallel.
8+
* The calls to `iteratee` will be performed in a queue to limit the concurrency of these calls.
89
*
9-
* If any of the calls to iteratee throws an exception the returned promise will be rejected.
10+
* If any of the calls to iteratee throws an exception the returned promise will be rejected and the remaining
11+
* pending tasks will be cancelled.
1012
*
1113
* @param {Iterable | AsyncIterable} iterable An iterable or async iterable object.
1214
* @param {Function} iteratee A function that will be called with each member of the iterable. It will receive
1315
* three arguments:
1416
* * `value`: The current value to process
1517
* * `index`: The index in the iterable. Will start from 0.
1618
* * `iterable`: The iterable on which the operation is being performed.
19+
* @param {Queue | number} queueOrConcurrency If a queue is specified it will be used to schedule the calls to
20+
* `iteratee`. If a number is specified it will be used as the concurrency of a Queue that will be created
21+
* implicitly for the same purpose. Defaults to `1`.
1722
* @returns {Promise} A promise that will be resolved when all the calls to `iteratee` have been done.
1823
* This promise will be rejected if any call to `iteratee` throws an exception.
1924
* @example
2025
* import { forEach, sleep } from 'modern-async'
2126
*
2227
* const array = [1, 2, 3]
2328
* await forEach(array, async (v) => {
24-
* // these calls will be performed in parallel
29+
* // these calls will be performed in parallel with a maximum of 2
30+
* // concurrent calls
2531
* await sleep(Math.random() * 10) // waits a random amount of time between 0ms and 10ms
2632
* console.log(v)
27-
* })
28-
* // prints 1, 2 and 3 in a random order
29-
* })
33+
* }, 2)
34+
* // prints 1, 2 and 3 in a random order (it will always print 1 or 2 before printing 3 due to
35+
* // the concurrency limit and the internal scheduling order)
3036
*/
31-
async function forEach (iterable, iteratee) {
32-
return forEachLimit(iterable, iteratee, Number.POSITIVE_INFINITY)
37+
async function forEach (iterable, iteratee, queueOrConcurrency = 1) {
38+
// eslint-disable-next-line no-unused-vars
39+
for await (const _el of mapGenerator(iterable, iteratee, queueOrConcurrency)) {
40+
// do nothing
41+
}
3342
}
3443

3544
export default forEach

src/forEach.test.mjs

Lines changed: 127 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,15 @@ import { expect, test } from '@jest/globals'
33
import forEach from './forEach.mjs'
44
import Deferred from './Deferred.mjs'
55
import { range } from 'itertools'
6+
import delay from './delay.mjs'
67

78
test('forEach base', async () => {
89
const arr = [...range(6)]
910
const called = {}
1011
arr.forEach((v) => { called[v] = 0 })
1112
await forEach(arr, async (x) => {
1213
called[x] += 1
13-
})
14+
}, 2)
1415
expect(called[0]).toBe(1)
1516
expect(called[1]).toBe(1)
1617
expect(called[2]).toBe(1)
@@ -25,7 +26,7 @@ test('forEach no async', async () => {
2526
arr.forEach((v) => { called[v] = 0 })
2627
await forEach(arr, (x) => {
2728
called[x] += 1
28-
})
29+
}, 2)
2930
expect(called[0]).toBe(1)
3031
expect(called[1]).toBe(1)
3132
expect(called[2]).toBe(1)
@@ -44,7 +45,72 @@ test('forEach concurrency', async () => {
4445
called[x] += 1
4546
ds[x].resolve()
4647
await d.promise
47-
})
48+
}, 2)
49+
await ds[1].promise
50+
expect(called[0]).toBe(1)
51+
expect(called[1]).toBe(1)
52+
expect(called[2]).toBe(0)
53+
expect(called[3]).toBe(0)
54+
expect(called[4]).toBe(0)
55+
expect(called[5]).toBe(0)
56+
await delay()
57+
expect(called[0]).toBe(1)
58+
expect(called[1]).toBe(1)
59+
expect(called[2]).toBe(0)
60+
expect(called[3]).toBe(0)
61+
expect(called[4]).toBe(0)
62+
expect(called[5]).toBe(0)
63+
d.resolve()
64+
await p
65+
expect(called[0]).toBe(1)
66+
expect(called[1]).toBe(1)
67+
expect(called[2]).toBe(1)
68+
expect(called[3]).toBe(1)
69+
expect(called[4]).toBe(1)
70+
expect(called[5]).toBe(1)
71+
})
72+
73+
test('forEach infinite concurrency base', async () => {
74+
const arr = [...range(6)]
75+
const called = {}
76+
arr.forEach((v) => { called[v] = 0 })
77+
await forEach(arr, async (x) => {
78+
called[x] += 1
79+
}, Number.POSITIVE_INFINITY)
80+
expect(called[0]).toBe(1)
81+
expect(called[1]).toBe(1)
82+
expect(called[2]).toBe(1)
83+
expect(called[3]).toBe(1)
84+
expect(called[4]).toBe(1)
85+
expect(called[5]).toBe(1)
86+
})
87+
88+
test('forEach infinite concurrency no async', async () => {
89+
const arr = [...range(6)]
90+
const called = {}
91+
arr.forEach((v) => { called[v] = 0 })
92+
await forEach(arr, (x) => {
93+
called[x] += 1
94+
}, Number.POSITIVE_INFINITY)
95+
expect(called[0]).toBe(1)
96+
expect(called[1]).toBe(1)
97+
expect(called[2]).toBe(1)
98+
expect(called[3]).toBe(1)
99+
expect(called[4]).toBe(1)
100+
expect(called[5]).toBe(1)
101+
})
102+
103+
test('forEach infinite concurrency concurrency', async () => {
104+
const arr = [...range(6)]
105+
const called = {}
106+
arr.forEach((v) => { called[v] = 0 })
107+
const d = new Deferred()
108+
const ds = arr.map(() => new Deferred())
109+
const p = forEach(arr, async (x) => {
110+
called[x] += 1
111+
ds[x].resolve()
112+
await d.promise
113+
}, Number.POSITIVE_INFINITY)
48114
await ds[5].promise
49115
expect(called[0]).toBe(1)
50116
expect(called[1]).toBe(1)
@@ -61,3 +127,61 @@ test('forEach concurrency', async () => {
61127
expect(called[4]).toBe(1)
62128
expect(called[5]).toBe(1)
63129
})
130+
131+
test('forEach concurrency 1 base', async () => {
132+
const arr = [...range(6)]
133+
const called = {}
134+
arr.forEach((v) => { called[v] = 0 })
135+
await forEach(arr, async (x) => {
136+
called[x] += 1
137+
})
138+
expect(called[0]).toBe(1)
139+
expect(called[1]).toBe(1)
140+
expect(called[2]).toBe(1)
141+
expect(called[3]).toBe(1)
142+
expect(called[4]).toBe(1)
143+
expect(called[5]).toBe(1)
144+
})
145+
146+
test('forEach concurrency 1 no async', async () => {
147+
const arr = [...range(6)]
148+
const called = {}
149+
arr.forEach((v) => { called[v] = 0 })
150+
await forEach(arr, (x) => {
151+
called[x] += 1
152+
})
153+
expect(called[0]).toBe(1)
154+
expect(called[1]).toBe(1)
155+
expect(called[2]).toBe(1)
156+
expect(called[3]).toBe(1)
157+
expect(called[4]).toBe(1)
158+
expect(called[5]).toBe(1)
159+
})
160+
161+
test('forEach concurrency 1 concurrency', async () => {
162+
const arr = [...range(6)]
163+
const called = {}
164+
arr.forEach((v) => { called[v] = 0 })
165+
const d = new Deferred()
166+
const ds = arr.map(() => new Deferred())
167+
const p = forEach(arr, async (x) => {
168+
called[x] += 1
169+
ds[x].resolve()
170+
await d.promise
171+
})
172+
await ds[0].promise
173+
expect(called[0]).toBe(1)
174+
expect(called[1]).toBe(0)
175+
expect(called[2]).toBe(0)
176+
expect(called[3]).toBe(0)
177+
expect(called[4]).toBe(0)
178+
expect(called[5]).toBe(0)
179+
d.resolve()
180+
await p
181+
expect(called[0]).toBe(1)
182+
expect(called[1]).toBe(1)
183+
expect(called[2]).toBe(1)
184+
expect(called[3]).toBe(1)
185+
expect(called[4]).toBe(1)
186+
expect(called[5]).toBe(1)
187+
})

src/forEachLimit.mjs

Lines changed: 0 additions & 44 deletions
This file was deleted.

src/forEachLimit.test.mjs

Lines changed: 0 additions & 71 deletions
This file was deleted.

src/forEachSeries.mjs

Lines changed: 0 additions & 35 deletions
This file was deleted.

0 commit comments

Comments
 (0)