Skip to content

Commit cb6e02b

Browse files
committed
Renamed some*
1 parent 89cfc93 commit cb6e02b

File tree

8 files changed

+153
-251
lines changed

8 files changed

+153
-251
lines changed

modern-async.d.ts

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -145,18 +145,10 @@ declare module "sleepPrecise" {
145145
export default sleepPrecise;
146146
function sleepPrecise(amount: number): Promise<void>;
147147
}
148-
declare module "someLimit" {
149-
export default someLimit;
150-
function someLimit<V>(iterable: Iterable<V> | AsyncIterable<V>, iteratee: (value: V, index: number, iterable: Iterable<V> | AsyncIterable<V>) => Promise<boolean> | boolean, queueOrConcurrency: Queue | number): Promise<boolean>;
151-
import Queue from "Queue";
152-
}
153148
declare module "some" {
154149
export default some;
155-
function some<V>(iterable: Iterable<V> | AsyncIterable<V>, iteratee: (value: V, index: number, iterable: Iterable<V> | AsyncIterable<V>) => Promise<boolean> | boolean): Promise<boolean>;
156-
}
157-
declare module "someSeries" {
158-
export default someSeries;
159-
function someSeries<V>(iterable: Iterable<V> | AsyncIterable<V>, iteratee: (value: V, index: number, iterable: Iterable<V> | AsyncIterable<V>) => Promise<boolean> | boolean): Promise<boolean>;
150+
function some<V>(iterable: Iterable<V> | AsyncIterable<V>, iteratee: (value: V, index: number, iterable: Iterable<V> | AsyncIterable<V>) => Promise<boolean> | boolean, queueOrConcurrency?: Queue | number): Promise<boolean>;
151+
import Queue from "Queue";
160152
}
161153
declare module "TimeoutError" {
162154
export default TimeoutError;
@@ -203,8 +195,6 @@ declare module "modern-async" {
203195
export { default as sleepPrecise } from "sleepPrecise";
204196
export { default as sleepPreciseCancellable } from "sleepPreciseCancellable";
205197
export { default as some } from "some";
206-
export { default as someLimit } from "someLimit";
207-
export { default as someSeries } from "someSeries";
208198
export { default as timeout } from "timeout";
209199
export { default as TimeoutError } from "TimeoutError";
210200
export { default as timeoutPrecise } from "timeoutPrecise";

src/modern-async.mjs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,6 @@ export { default as sleepCancellable } from './sleepCancellable.mjs'
2525
export { default as sleepPrecise } from './sleepPrecise.mjs'
2626
export { default as sleepPreciseCancellable } from './sleepPreciseCancellable.mjs'
2727
export { default as some } from './some.mjs'
28-
export { default as someLimit } from './someLimit.mjs'
29-
export { default as someSeries } from './someSeries.mjs'
3028
export { default as timeout } from './timeout.mjs'
3129
export { default as TimeoutError } from './TimeoutError.mjs'
3230
export { default as timeoutPrecise } from './timeoutPrecise.mjs'

src/some.mjs

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,28 @@
11

2-
import someLimit from './someLimit.mjs'
2+
import findIndex from './findIndex.mjs'
3+
import Queue from './Queue.mjs'
34

45
/**
56
* Returns `true` if at least one element of an iterable pass a truth test and `false` otherwise.
67
*
7-
* The calls to `iteratee` will run in parallel. If any truth test returns `true` the promise is immediately resolved.
8+
* The calls to `iteratee` will be performed in a queue to limit the concurrency of these calls. If any
9+
* truth test returns `true` the promise is immediately resolved.
810
*
9-
* In case of exception in one of the `iteratee` calls the promise returned by this function will be rejected
10-
* with the exception. In the very specific case where a test returns `true` and an already started task throws
11-
* an exception that exception will be plainly ignored.
11+
* Whenever a test returns `true`, all the remaining tasks will be cancelled as long
12+
* as they didn't started already. In case of exception in one of the `iteratee` calls the promise
13+
* returned by this function will be rejected with the exception and the remaining pending
14+
* tasks will also be cancelled. In the very specific case where a test returns `true` and an
15+
* already started task throws an exception that exception will be plainly ignored.
1216
*
1317
* @param {Iterable | AsyncIterable} iterable An iterable or async iterable object.
1418
* @param {Function} iteratee A function that will be called with each member of the iterable. It will receive
1519
* three arguments:
1620
* * `value`: The current value to process
1721
* * `index`: The index in the iterable. Will start from 0.
1822
* * `iterable`: The iterable on which the operation is being performed.
23+
* @param {Queue | number} queueOrConcurrency If a queue is specified it will be used to schedule the calls to
24+
* `iteratee`. If a number is specified it will be used as the concurrency of a Queue that will be created
25+
* implicitly for the same purpose. Defaults to `1`.
1926
* @returns {Promise<boolean>} A promise that will be resolved to `true` if at least one value pass the truth test and `false`
2027
* if none of them do. That promise will be rejected if one of the truth test throws an exception.
2128
* @example
@@ -24,15 +31,18 @@ import someLimit from './someLimit.mjs'
2431
* const array = [1, 2, 3]
2532
*
2633
* const result = await some(array, async (v) => {
27-
* // these calls will be performed in parallel
34+
* // these calls will be performed in parallel with a maximum of 2
35+
* // concurrent calls
2836
* await sleep(10) // waits 10ms
2937
* return v % 2 === 0
30-
* })
38+
* }, 2)
3139
* console.log(result) // prints true
3240
* // total processing time should be ~ 10ms
3341
*/
34-
async function some (iterable, iteratee) {
35-
return someLimit(iterable, iteratee, Number.POSITIVE_INFINITY)
42+
async function some (iterable, iteratee, queueOrConcurrency = 1) {
43+
const index = await findIndex(iterable, iteratee, queueOrConcurrency, false)
44+
const result = index !== -1
45+
return result
3646
}
3747

3848
export default some

src/some.test.mjs

Lines changed: 132 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,87 @@
11

22
import { expect, test } from '@jest/globals'
33
import some from './some.mjs'
4-
import Deferred from './Deferred.mjs'
54
import { range } from 'itertools'
5+
import Deferred from './Deferred.mjs'
6+
7+
test('some compatibility', async () => {
8+
const p = Promise.resolve()
9+
let res = await some([...range(3)], async (v) => {
10+
await p
11+
return true
12+
}, 1)
13+
expect(res).toBe([...range(3)].some((v) => true))
614

7-
test('some all no pass', async () => {
15+
res = await some([...range(3)], async (v) => {
16+
await p
17+
return v !== 2
18+
}, 1)
19+
expect(res).toBe([...range(3)].some((v) => v !== 2))
20+
21+
res = await some([...range(3)], async (v) => {
22+
await p
23+
return false
24+
}, 1)
25+
expect(res).toBe([...range(3)].some((v) => false))
26+
27+
res = await some([], async (v) => {
28+
await p
29+
return false
30+
}, 1)
31+
expect(res).toBe([].some((v) => false))
32+
33+
res = await some([], async (v) => {
34+
await p
35+
return true
36+
}, 1)
37+
expect(res).toBe([].some((v) => true))
38+
})
39+
40+
test('some parallel', async () => {
41+
const p = Promise.resolve()
42+
let res = await some([...range(3)], async (v) => {
43+
await p
44+
return true
45+
}, 10)
46+
expect(res).toBe([...range(3)].some((v) => true))
47+
48+
res = await some([...range(3)], async (v) => {
49+
await p
50+
return v !== 2
51+
}, 10)
52+
expect(res).toBe([...range(3)].some((v) => v !== 2))
53+
54+
res = await some([...range(3)], async (v) => {
55+
await p
56+
return false
57+
}, 10)
58+
expect(res).toBe([...range(3)].some((v) => false))
59+
60+
res = await some([], async (v) => {
61+
await p
62+
return false
63+
}, 10)
64+
expect(res).toBe([].some((v) => false))
65+
66+
res = await some([], async (v) => {
67+
await p
68+
return true
69+
}, 10)
70+
expect(res).toBe([].some((v) => true))
71+
})
72+
73+
test('some first in time', async () => {
74+
const ds = [...range(3)].map(() => new Deferred())
75+
const p = some(range(3), async (v, i) => {
76+
await ds[i]
77+
return true
78+
}, 3)
79+
ds[2].resolve()
80+
const res = await p
81+
expect(res).toBe(true)
82+
})
83+
84+
test('some infinite concurrency all no pass', async () => {
885
const callCount = {}
986
;[...range(3)].forEach((i) => { callCount[i] = 0 })
1087
const d = new Deferred()
@@ -14,7 +91,7 @@ test('some all no pass', async () => {
1491
ds[i].resolve()
1592
await d.promise
1693
return false
17-
})
94+
}, Number.POSITIVE_INFINITY)
1895
await ds[2].promise
1996
expect(callCount[0]).toBe(1)
2097
expect(callCount[1]).toBe(1)
@@ -27,7 +104,7 @@ test('some all no pass', async () => {
27104
expect(callCount[2]).toBe(1)
28105
})
29106

30-
test('some some pass', async () => {
107+
test('some infinite concurrency some pass', async () => {
31108
const callCount = {}
32109
;[...range(3)].forEach((i) => { callCount[i] = 0 })
33110
const d = new Deferred()
@@ -41,7 +118,7 @@ test('some some pass', async () => {
41118
} else {
42119
return false
43120
}
44-
})
121+
}, Number.POSITIVE_INFINITY)
45122
await ds[2].promise
46123
expect(callCount[0]).toBe(1)
47124
expect(callCount[1]).toBe(1)
@@ -53,3 +130,53 @@ test('some some pass', async () => {
53130
expect(callCount[1]).toBe(1)
54131
expect(callCount[2]).toBe(1)
55132
})
133+
134+
test('some concurrency 1 all no pass', async () => {
135+
const callCount = {}
136+
;[...range(3)].forEach((i) => { callCount[i] = 0 })
137+
const d = new Deferred()
138+
const ds = [...range(3)].map(() => new Deferred())
139+
const p = some([...range(3)], async (v, i) => {
140+
callCount[i] += 1
141+
ds[i].resolve()
142+
await d.promise
143+
return false
144+
})
145+
await ds[0].promise
146+
expect(callCount[0]).toBe(1)
147+
expect(callCount[1]).toBe(0)
148+
expect(callCount[2]).toBe(0)
149+
d.resolve()
150+
const res = await p
151+
expect(res).toBe(false)
152+
expect(callCount[0]).toBe(1)
153+
expect(callCount[1]).toBe(1)
154+
expect(callCount[2]).toBe(1)
155+
})
156+
157+
test('some concurrency 1 some pass', async () => {
158+
const callCount = {}
159+
;[...range(3)].forEach((i) => { callCount[i] = 0 })
160+
const d = new Deferred()
161+
const ds = [...range(3)].map(() => new Deferred())
162+
const p = some([...range(3)], async (v, i) => {
163+
callCount[i] += 1
164+
ds[i].resolve()
165+
await d.promise
166+
if (i === 1) {
167+
return true
168+
} else {
169+
return false
170+
}
171+
})
172+
await ds[0].promise
173+
expect(callCount[0]).toBe(1)
174+
expect(callCount[1]).toBe(0)
175+
expect(callCount[2]).toBe(0)
176+
d.resolve()
177+
const res = await p
178+
expect(res).toBe(true)
179+
expect(callCount[0]).toBe(1)
180+
expect(callCount[1]).toBe(1)
181+
expect(callCount[2]).toBe(0)
182+
})

src/someLimit.mjs

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

src/someLimit.test.mjs

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

0 commit comments

Comments
 (0)