Skip to content

Commit 89cfc93

Browse files
committed
Renamed map*
1 parent 16dfe42 commit 89cfc93

10 files changed

+194
-287
lines changed

modern-async.d.ts

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ declare module "Queue" {
6060
}
6161
declare module "every" {
6262
export default every;
63-
function every<V>(iterable: Iterable<V> | AsyncIterable<V>, iteratee: (value: V, index: number, iterable: Iterable<V> | AsyncIterable<V>) => Promise<boolean> | boolean, queueOrConcurrency: Queue | number): Promise<boolean>;
63+
function every<V>(iterable: Iterable<V> | AsyncIterable<V>, iteratee: (value: V, index: number, iterable: Iterable<V> | AsyncIterable<V>) => Promise<boolean> | boolean, queueOrConcurrency?: Queue | number): Promise<boolean>;
6464
import Queue from "Queue";
6565
}
6666
declare module "toArray" {
@@ -89,26 +89,18 @@ declare module "find" {
8989
}
9090
declare module "findIndex" {
9191
export default findIndex;
92-
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>;
92+
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
}
9595
declare module "forEach" {
9696
export default forEach;
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";
99-
}
100-
declare module "mapLimit" {
101-
export default mapLimit;
102-
function mapLimit<V, M>(iterable: Iterable<V> | AsyncIterable<V>, iteratee: (value: V, index: number, iterable: Iterable<V> | AsyncIterable<V>) => Promise<M> | M, queueOrConcurrency: Queue | number): Promise<M[]>;
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>;
10398
import Queue from "Queue";
10499
}
105100
declare module "map" {
106101
export default map;
107-
function map<V, M>(iterable: Iterable<V> | AsyncIterable<V>, iteratee: (value: V, index: number, iterable: Iterable<V> | AsyncIterable<V>) => Promise<M> | M): Promise<M[]>;
108-
}
109-
declare module "mapSeries" {
110-
export default mapSeries;
111-
function mapSeries<V, M>(iterable: Iterable<V> | AsyncIterable<V>, iteratee: (value: V, index: number, iterable: Iterable<V> | AsyncIterable<V>) => Promise<M> | M): Promise<M[]>;
102+
function map<V, M>(iterable: Iterable<V> | AsyncIterable<V>, iteratee: (value: V, index: number, iterable: Iterable<V> | AsyncIterable<V>) => Promise<M> | M, queueOrConcurrency?: Queue | number): Promise<M[]>;
103+
import Queue from "Queue";
112104
}
113105
declare module "reduce" {
114106
export default reduce;
@@ -201,8 +193,6 @@ declare module "modern-async" {
201193
export { default as forEach } from "forEach";
202194
export { default as map } from "map";
203195
export { default as mapGenerator } from "mapGenerator";
204-
export { default as mapLimit } from "mapLimit";
205-
export { default as mapSeries } from "mapSeries";
206196
export { default as Queue } from "Queue";
207197
export { default as queueMicrotask } from "queueMicrotask";
208198
export { default as reduce } from "reduce";

src/filterGenerator.mjs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,10 @@ import asyncWrap from './asyncWrap.mjs'
2525
* * `iterable`: The iterable on which the operation is being performed.
2626
* @param {Queue | number} [queueOrConcurrency] If a queue is specified it will be used to schedule the calls to
2727
* `iteratee`. If a number is specified it will be used as the concurrency of a Queue that will be created
28-
* implicitly for the same purpose.
28+
* implicitly for the same purpose. Defaults to `1`.
2929
* @param {boolean} [ordered] If true the results will be yielded in the same order as in the source
3030
* iterable, regardless of which calls to iteratee returned first. If false the the results will be yielded as soon
31-
* as a call to iteratee returned.
31+
* as a call to iteratee returned. Defaults to `true`.
3232
* @yields {any} Each element of `iterable` for which `iteratee` returned `true`.
3333
* @example
3434
* import {filterGenerator, sleep} from 'modern-async'

src/map.mjs

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,42 @@
11

2-
import mapLimit from './mapLimit.mjs'
2+
import mapGenerator from './mapGenerator.mjs'
3+
import Queue from './Queue.mjs'
4+
import toArray from './toArray.mjs'
35

46
/**
57
* Produces a new collection of values by mapping each value in `iterable` through the `iteratee` function.
68
*
7-
* Multiple calls to `iteratee` will be performed in parallel.
9+
* The calls to `iteratee` will be performed in a queue to limit the concurrency of these calls.
810
*
9-
* If any of the calls to iteratee throws an exception the returned promise will be rejected.
11+
* If any of the calls to iteratee throws an exception the returned promise will be rejected and the remaining
12+
* pending tasks will be cancelled.
1013
*
1114
* @param {Iterable | AsyncIterable} iterable An iterable or async iterable object.
1215
* @param {Function} iteratee A function that will be called with each member of the iterable. It will receive
1316
* three arguments:
1417
* * `value`: The current value to process
1518
* * `index`: The index in the iterable. Will start from 0.
1619
* * `iterable`: The iterable on which the operation is being performed.
20+
* @param {Queue | number} queueOrConcurrency If a queue is specified it will be used to schedule the calls to
21+
* `iteratee`. If a number is specified it will be used as the concurrency of a Queue that will be created
22+
* implicitly for the same purpose. Defaults to `1`.
1723
* @returns {Promise<any[]>} A promise that will be resolved with an array containing all the mapped value,
1824
* or will be rejected if any of the calls to `iteratee` throws an exception.
1925
* @example
2026
* import { map, sleep } from 'modern-async'
2127
*
2228
* const array = [1, 2, 3]
2329
* const result = await map(array, async (v) => {
24-
* // these calls will be performed in parallel
30+
* // these calls will be performed in parallel with a maximum of 2
31+
* // concurrent calls
2532
* await sleep(10) // waits 10ms
2633
* return v * 2
27-
* })
34+
* }, 2)
2835
* console.log(result) // prints [2, 4, 6]
29-
* // total processing time should be ~ 10ms
36+
* // total processing time should be ~ 20ms
3037
*/
31-
async function map (iterable, iteratee) {
32-
return mapLimit(iterable, iteratee, Number.POSITIVE_INFINITY)
38+
async function map (iterable, iteratee, queueOrConcurrency = 1) {
39+
return await toArray(mapGenerator(iterable, iteratee, queueOrConcurrency))
3340
}
3441

3542
export default map

src/map.test.mjs

Lines changed: 170 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@ import { range } from 'itertools'
66

77
test('map base', async () => {
88
const arr = [...range(6)]
9-
const res = await map(arr, async (x) => x * 2)
9+
const res = await map(arr, async (x) => x * 2, 2)
1010
expect(res).toEqual([0, 2, 4, 6, 8, 10])
1111
})
1212

1313
test('map no async', async () => {
1414
const arr = [...range(6)]
15-
const res = await map(arr, (x) => x * 2)
15+
const res = await map(arr, (x) => x * 2, 2)
1616
expect(res).toEqual([0, 2, 4, 6, 8, 10])
1717
})
1818

@@ -27,7 +27,132 @@ test('map concurrency', async () => {
2727
ds[x].resolve()
2828
await d.promise
2929
return x * 2
30-
})
30+
}, 2)
31+
await ds[1].promise
32+
expect(called[0]).toBe(1)
33+
expect(called[1]).toBe(1)
34+
expect(called[2]).toBe(0)
35+
expect(called[3]).toBe(0)
36+
expect(called[4]).toBe(0)
37+
expect(called[5]).toBe(0)
38+
d.resolve()
39+
const res = await p
40+
expect(res).toEqual([0, 2, 4, 6, 8, 10])
41+
expect(called[0]).toBe(1)
42+
expect(called[1]).toBe(1)
43+
expect(called[2]).toBe(1)
44+
expect(called[3]).toBe(1)
45+
expect(called[4]).toBe(1)
46+
expect(called[5]).toBe(1)
47+
})
48+
49+
test('map index & iterable', async () => {
50+
const arr = [...range(6)]
51+
const res = await map(arr, async (x, index, iterable) => {
52+
expect(index).toBe(x)
53+
expect(iterable).toBe(arr)
54+
return x * 2
55+
}, 2)
56+
expect(res).toEqual([0, 2, 4, 6, 8, 10])
57+
})
58+
59+
test('map one exception', async () => {
60+
const arr = [...range(3)]
61+
const called = {}
62+
arr.forEach((v) => { called[v] = 0 })
63+
try {
64+
const d = new Deferred()
65+
const p = map(arr, async (x) => {
66+
called[x] += 1
67+
await d.promise
68+
if (x === 1) {
69+
throw new Error('test')
70+
}
71+
return x * 2
72+
}, 1)
73+
d.resolve()
74+
await p
75+
expect(false).toBe(true)
76+
} catch (e) {
77+
expect(e.message).toBe('test')
78+
}
79+
expect(called[0]).toBe(1)
80+
expect(called[1]).toBe(1)
81+
expect(called[2]).toBe(0)
82+
})
83+
84+
test('map all exception c 1', async () => {
85+
const arr = [...range(3)]
86+
const called = {}
87+
arr.forEach((v) => { called[v] = 0 })
88+
try {
89+
const d = new Deferred()
90+
const p = map(arr, async (x) => {
91+
called[x] += 1
92+
await d.promise
93+
throw new Error('test')
94+
}, 1)
95+
d.resolve()
96+
await p
97+
expect(false).toBe(true)
98+
} catch (e) {
99+
expect(e.message).toBe('test')
100+
}
101+
expect(called[0]).toBe(1)
102+
expect(called[1]).toBe(0)
103+
expect(called[2]).toBe(0)
104+
})
105+
106+
test('map all exception c 2', async () => {
107+
const arr = [...range(3)]
108+
const called = {}
109+
arr.forEach((v) => { called[v] = 0 })
110+
const ds = arr.map(() => new Deferred())
111+
try {
112+
const d = new Deferred()
113+
const p = map(arr, async (x) => {
114+
called[x] += 1
115+
ds[x].resolve()
116+
await d.promise
117+
throw new Error('test')
118+
}, 2)
119+
await ds[0].promise
120+
await ds[1].promise
121+
d.resolve()
122+
await p
123+
expect(false).toBe(true)
124+
} catch (e) {
125+
expect(e.message).toBe('test')
126+
}
127+
expect(called[0]).toBe(1)
128+
expect(called[1]).toBe(1)
129+
expect(called[2]).toBe(0)
130+
})
131+
132+
test('map infinite concurrency base', async () => {
133+
const arr = [...range(6)]
134+
const res = await map(arr, async (x) => x * 2, Number.POSITIVE_INFINITY)
135+
expect(res).toEqual([0, 2, 4, 6, 8, 10])
136+
})
137+
138+
test('map infinite concurrency no async', async () => {
139+
const arr = [...range(6)]
140+
const res = await map(arr, (x) => x * 2, Number.POSITIVE_INFINITY)
141+
expect(res).toEqual([0, 2, 4, 6, 8, 10])
142+
})
143+
144+
test('map infinite concurrency concurrency', async () => {
145+
const arr = [...range(6)]
146+
const called = {}
147+
arr.forEach((v) => { called[v] = 0 })
148+
const d = new Deferred()
149+
const ds = arr.map(() => new Deferred())
150+
const p = map(arr, async (x) => {
151+
called[x] += 1
152+
ds[x].resolve()
153+
await d.promise
154+
return x * 2
155+
}, Number.POSITIVE_INFINITY)
31156
await ds[5].promise
32157
expect(called[0]).toBe(1)
33158
expect(called[1]).toBe(1)
@@ -45,3 +170,45 @@ test('map concurrency', async () => {
45170
expect(called[4]).toBe(1)
46171
expect(called[5]).toBe(1)
47172
})
173+
174+
test('map concurrency 1 base', async () => {
175+
const arr = [...range(6)]
176+
const res = await map(arr, async (x) => x * 2)
177+
expect(res).toEqual([0, 2, 4, 6, 8, 10])
178+
})
179+
180+
test('map concurrency 1 no async', async () => {
181+
const arr = [...range(6)]
182+
const res = await map(arr, (x) => x * 2)
183+
expect(res).toEqual([0, 2, 4, 6, 8, 10])
184+
})
185+
186+
test('map concurrency 1 concurrency', async () => {
187+
const arr = [...range(6)]
188+
const called = {}
189+
arr.forEach((v) => { called[v] = 0 })
190+
const d = new Deferred()
191+
const ds = arr.map(() => new Deferred())
192+
const p = map(arr, async (x) => {
193+
ds[x].resolve()
194+
called[x] += 1
195+
await d.promise
196+
return x * 2
197+
})
198+
await ds[0].promise
199+
expect(called[0]).toBe(1)
200+
expect(called[1]).toBe(0)
201+
expect(called[2]).toBe(0)
202+
expect(called[3]).toBe(0)
203+
expect(called[4]).toBe(0)
204+
expect(called[5]).toBe(0)
205+
d.resolve()
206+
const res = await p
207+
expect(res).toEqual([0, 2, 4, 6, 8, 10])
208+
expect(called[0]).toBe(1)
209+
expect(called[1]).toBe(1)
210+
expect(called[2]).toBe(1)
211+
expect(called[3]).toBe(1)
212+
expect(called[4]).toBe(1)
213+
expect(called[5]).toBe(1)
214+
})

src/mapGenerator.mjs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,10 @@ import reflectStatus from './reflectStatus.mjs'
2828
* * `iterable`: The iterable on which the operation is being performed.
2929
* @param {Queue | number} [queueOrConcurrency] If a queue is specified it will be used to schedule the calls to
3030
* `iteratee`. If a number is specified it will be used as the concurrency of a Queue that will be created
31-
* implicitly for the same purpose.
31+
* implicitly for the same purpose. Defaults to `1`.
3232
* @param {boolean} [ordered] If true the results will be yielded in the same order as in the source
3333
* iterable, regardless of which calls to iteratee returned first. If false the the results will be yielded as soon
34-
* as a call to iteratee returned.
34+
* as a call to iteratee returned. Defaults to `true`.
3535
* @yields {any} Each element of `iterable` after processing it through `iteratee`.
3636
* @example
3737
* import {mapGenerator, sleep} from 'modern-async'

src/mapLimit.mjs

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

0 commit comments

Comments
 (0)