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.
52 lines
1.2 KiB
52 lines
1.2 KiB
'use strict'; |
|
const pLimit = require('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; |
|
}; |
|
|
|
const pLocate = async (iterable, tester, options) => { |
|
options = { |
|
concurrency: Infinity, |
|
preserveOrder: true, |
|
...options |
|
}; |
|
|
|
const limit = pLimit(options.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(options.preserveOrder ? 1 : Infinity); |
|
|
|
try { |
|
await Promise.all(items.map(element => checkLimit(finder, element))); |
|
} catch (error) { |
|
if (error instanceof EndError) { |
|
return error.value; |
|
} |
|
|
|
throw error; |
|
} |
|
}; |
|
|
|
module.exports = pLocate; |
|
// TODO: Remove this for the next major release |
|
module.exports.default = pLocate;
|
|
|