You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
48 lines
1.1 KiB
48 lines
1.1 KiB
import pLimit from 'p-limit'; |
|
|
|
class EndError extends Error { |
|
constructor(value) { |
|
super(); |
|
this.value = value; |
|
} |
|
} |
|
|
|
// The input can also be a promise, so we await it. |
|
const testElement = async (element, tester) => tester(await element); |
|
|
|
// The input can also be a promise, so we `Promise.all()` them both. |
|
const finder = async element => { |
|
const values = await Promise.all(element); |
|
if (values[1] === true) { |
|
throw new EndError(values[0]); |
|
} |
|
|
|
return false; |
|
}; |
|
|
|
export default async function pLocate( |
|
iterable, |
|
tester, |
|
{ |
|
concurrency = Number.POSITIVE_INFINITY, |
|
preserveOrder = true, |
|
} = {}, |
|
) { |
|
const limit = pLimit(concurrency); |
|
|
|
// Start all the promises concurrently with optional limit. |
|
const items = [...iterable].map(element => [element, limit(testElement, element, tester)]); |
|
|
|
// Check the promises either serially or concurrently. |
|
const checkLimit = pLimit(preserveOrder ? 1 : Number.POSITIVE_INFINITY); |
|
|
|
try { |
|
await Promise.all(items.map(element => checkLimit(finder, element))); |
|
} catch (error) { |
|
if (error instanceof EndError) { |
|
return error.value; |
|
} |
|
|
|
throw error; |
|
} |
|
}
|
|
|