UNPKG

1.12 kBJavaScriptView Raw
1import pLimit from 'p-limit';
2
3class EndError extends Error {
4 constructor(value) {
5 super();
6 this.value = value;
7 }
8}
9
10// The input can also be a promise, so we await it.
11const testElement = async (element, tester) => tester(await element);
12
13// The input can also be a promise, so we `Promise.all()` them both.
14const 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
23export 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 // Start all the promises concurrently with optional limit.
34 const items = [...iterable].map(element => [element, limit(testElement, element, tester)]);
35
36 // Check the promises either serially or concurrently.
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}