1 | import pLimit from 'p-limit';
|
2 |
|
3 | class EndError extends Error {
|
4 | constructor(value) {
|
5 | super();
|
6 | this.value = value;
|
7 | }
|
8 | }
|
9 |
|
10 |
|
11 | const testElement = async (element, tester) => tester(await element);
|
12 |
|
13 |
|
14 | const finder = async element => {
|
15 | const values = await Promise.all(element);
|
16 | if (values[1] === true) {
|
17 | throw new EndError(values[0]);
|
18 | }
|
19 |
|
20 | return false;
|
21 | };
|
22 |
|
23 | export default async function pLocate(
|
24 | iterable,
|
25 | tester,
|
26 | {
|
27 | concurrency = Number.POSITIVE_INFINITY,
|
28 | preserveOrder = true,
|
29 | } = {},
|
30 | ) {
|
31 | const limit = pLimit(concurrency);
|
32 |
|
33 |
|
34 | const items = [...iterable].map(element => [element, limit(testElement, element, tester)]);
|
35 |
|
36 |
|
37 | const checkLimit = pLimit(preserveOrder ? 1 : Number.POSITIVE_INFINITY);
|
38 |
|
39 | try {
|
40 | await Promise.all(items.map(element => checkLimit(finder, element)));
|
41 | } catch (error) {
|
42 | if (error instanceof EndError) {
|
43 | return error.value;
|
44 | }
|
45 |
|
46 | throw error;
|
47 | }
|
48 | }
|