composeSignals.js 1.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
  1. import CanceledError from '../cancel/CanceledError.js';
  2. import AxiosError from '../core/AxiosError.js';
  3. import utils from '../utils.js';
  4. const composeSignals = (signals, timeout) => {
  5. const { length } = (signals = signals ? signals.filter(Boolean) : []);
  6. if (timeout || length) {
  7. let controller = new AbortController();
  8. let aborted;
  9. const onabort = function (reason) {
  10. if (!aborted) {
  11. aborted = true;
  12. unsubscribe();
  13. const err = reason instanceof Error ? reason : this.reason;
  14. controller.abort(
  15. err instanceof AxiosError
  16. ? err
  17. : new CanceledError(err instanceof Error ? err.message : err)
  18. );
  19. }
  20. };
  21. let timer =
  22. timeout &&
  23. setTimeout(() => {
  24. timer = null;
  25. onabort(new AxiosError(`timeout of ${timeout}ms exceeded`, AxiosError.ETIMEDOUT));
  26. }, timeout);
  27. const unsubscribe = () => {
  28. if (signals) {
  29. timer && clearTimeout(timer);
  30. timer = null;
  31. signals.forEach((signal) => {
  32. signal.unsubscribe
  33. ? signal.unsubscribe(onabort)
  34. : signal.removeEventListener('abort', onabort);
  35. });
  36. signals = null;
  37. }
  38. };
  39. signals.forEach((signal) => signal.addEventListener('abort', onabort));
  40. const { signal } = controller;
  41. signal.unsubscribe = () => utils.asap(unsubscribe);
  42. return signal;
  43. }
  44. };
  45. export default composeSignals;