index.js 1.1 KB

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