mapAsyncIterator.js 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849
  1. /**
  2. * Given an AsyncIterable and a callback function, return an AsyncIterator
  3. * which produces values mapped via calling the callback function.
  4. */
  5. export function mapAsyncIterator(iterator, callback, rejectCallback) {
  6. let $return;
  7. let abruptClose;
  8. if (typeof iterator.return === 'function') {
  9. $return = iterator.return;
  10. abruptClose = (error) => {
  11. const rethrow = () => Promise.reject(error);
  12. return $return.call(iterator).then(rethrow, rethrow);
  13. };
  14. }
  15. function mapResult(result) {
  16. return result.done ? result : asyncMapValue(result.value, callback).then(iteratorResult, abruptClose);
  17. }
  18. let mapReject;
  19. if (rejectCallback) {
  20. // Capture rejectCallback to ensure it cannot be null.
  21. const reject = rejectCallback;
  22. mapReject = (error) => asyncMapValue(error, reject).then(iteratorResult, abruptClose);
  23. }
  24. return {
  25. next() {
  26. return iterator.next().then(mapResult, mapReject);
  27. },
  28. return() {
  29. return $return
  30. ? $return.call(iterator).then(mapResult, mapReject)
  31. : Promise.resolve({ value: undefined, done: true });
  32. },
  33. throw(error) {
  34. if (typeof iterator.throw === 'function') {
  35. return iterator.throw(error).then(mapResult, mapReject);
  36. }
  37. return Promise.reject(error).catch(abruptClose);
  38. },
  39. [Symbol.asyncIterator]() {
  40. return this;
  41. },
  42. };
  43. }
  44. function asyncMapValue(value, callback) {
  45. return new Promise(resolve => resolve(callback(value)));
  46. }
  47. function iteratorResult(value) {
  48. return { value, done: false };
  49. }