index.js 1.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748
  1. import pLimit from 'p-limit';
  2. class EndError extends Error {
  3. constructor(value) {
  4. super();
  5. this.value = value;
  6. }
  7. }
  8. // The input can also be a promise, so we await it.
  9. const testElement = async (element, tester) => tester(await element);
  10. // The input can also be a promise, so we `Promise.all()` them both.
  11. const finder = async element => {
  12. const values = await Promise.all(element);
  13. if (values[1] === true) {
  14. throw new EndError(values[0]);
  15. }
  16. return false;
  17. };
  18. export default async function pLocate(
  19. iterable,
  20. tester,
  21. {
  22. concurrency = Number.POSITIVE_INFINITY,
  23. preserveOrder = true,
  24. } = {},
  25. ) {
  26. const limit = pLimit(concurrency);
  27. // Start all the promises concurrently with optional limit.
  28. const items = [...iterable].map(element => [element, limit(testElement, element, tester)]);
  29. // Check the promises either serially or concurrently.
  30. const checkLimit = pLimit(preserveOrder ? 1 : Number.POSITIVE_INFINITY);
  31. try {
  32. await Promise.all(items.map(element => checkLimit(finder, element)));
  33. } catch (error) {
  34. if (error instanceof EndError) {
  35. return error.value;
  36. }
  37. throw error;
  38. }
  39. }