withCancel.js 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
  1. import { memoize2 } from './memoize.js';
  2. async function defaultAsyncIteratorReturn(value) {
  3. return { value, done: true };
  4. }
  5. const proxyMethodFactory = memoize2(function proxyMethodFactory(target, targetMethod) {
  6. return function proxyMethod(...args) {
  7. return Reflect.apply(targetMethod, target, args);
  8. };
  9. });
  10. export function getAsyncIteratorWithCancel(asyncIterator, onCancel) {
  11. return new Proxy(asyncIterator, {
  12. has(asyncIterator, prop) {
  13. if (prop === 'return') {
  14. return true;
  15. }
  16. return Reflect.has(asyncIterator, prop);
  17. },
  18. get(asyncIterator, prop, receiver) {
  19. const existingPropValue = Reflect.get(asyncIterator, prop, receiver);
  20. if (prop === 'return') {
  21. const existingReturn = existingPropValue || defaultAsyncIteratorReturn;
  22. return async function returnWithCancel(value) {
  23. const returnValue = await onCancel(value);
  24. return Reflect.apply(existingReturn, asyncIterator, [returnValue]);
  25. };
  26. }
  27. else if (typeof existingPropValue === 'function') {
  28. return proxyMethodFactory(asyncIterator, existingPropValue);
  29. }
  30. return existingPropValue;
  31. },
  32. });
  33. }
  34. export function getAsyncIterableWithCancel(asyncIterable, onCancel) {
  35. return new Proxy(asyncIterable, {
  36. get(asyncIterable, prop, receiver) {
  37. const existingPropValue = Reflect.get(asyncIterable, prop, receiver);
  38. if (Symbol.asyncIterator === prop) {
  39. return function asyncIteratorFactory() {
  40. const asyncIterator = Reflect.apply(existingPropValue, asyncIterable, []);
  41. return getAsyncIteratorWithCancel(asyncIterator, onCancel);
  42. };
  43. }
  44. else if (typeof existingPropValue === 'function') {
  45. return proxyMethodFactory(asyncIterable, existingPropValue);
  46. }
  47. return existingPropValue;
  48. },
  49. });
  50. }
  51. export { getAsyncIterableWithCancel as withCancel };