retryer.esm.js 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. import { focusManager } from './focusManager.esm.js';
  2. import { onlineManager } from './onlineManager.esm.js';
  3. import { sleep } from './utils.esm.js';
  4. function defaultRetryDelay(failureCount) {
  5. return Math.min(1000 * 2 ** failureCount, 30000);
  6. }
  7. function canFetch(networkMode) {
  8. return (networkMode != null ? networkMode : 'online') === 'online' ? onlineManager.isOnline() : true;
  9. }
  10. class CancelledError {
  11. constructor(options) {
  12. this.revert = options == null ? void 0 : options.revert;
  13. this.silent = options == null ? void 0 : options.silent;
  14. }
  15. }
  16. function isCancelledError(value) {
  17. return value instanceof CancelledError;
  18. }
  19. function createRetryer(config) {
  20. let isRetryCancelled = false;
  21. let failureCount = 0;
  22. let isResolved = false;
  23. let continueFn;
  24. let promiseResolve;
  25. let promiseReject;
  26. const promise = new Promise((outerResolve, outerReject) => {
  27. promiseResolve = outerResolve;
  28. promiseReject = outerReject;
  29. });
  30. const cancel = cancelOptions => {
  31. if (!isResolved) {
  32. reject(new CancelledError(cancelOptions));
  33. config.abort == null ? void 0 : config.abort();
  34. }
  35. };
  36. const cancelRetry = () => {
  37. isRetryCancelled = true;
  38. };
  39. const continueRetry = () => {
  40. isRetryCancelled = false;
  41. };
  42. const shouldPause = () => !focusManager.isFocused() || config.networkMode !== 'always' && !onlineManager.isOnline();
  43. const resolve = value => {
  44. if (!isResolved) {
  45. isResolved = true;
  46. config.onSuccess == null ? void 0 : config.onSuccess(value);
  47. continueFn == null ? void 0 : continueFn();
  48. promiseResolve(value);
  49. }
  50. };
  51. const reject = value => {
  52. if (!isResolved) {
  53. isResolved = true;
  54. config.onError == null ? void 0 : config.onError(value);
  55. continueFn == null ? void 0 : continueFn();
  56. promiseReject(value);
  57. }
  58. };
  59. const pause = () => {
  60. return new Promise(continueResolve => {
  61. continueFn = value => {
  62. const canContinue = isResolved || !shouldPause();
  63. if (canContinue) {
  64. continueResolve(value);
  65. }
  66. return canContinue;
  67. };
  68. config.onPause == null ? void 0 : config.onPause();
  69. }).then(() => {
  70. continueFn = undefined;
  71. if (!isResolved) {
  72. config.onContinue == null ? void 0 : config.onContinue();
  73. }
  74. });
  75. }; // Create loop function
  76. const run = () => {
  77. // Do nothing if already resolved
  78. if (isResolved) {
  79. return;
  80. }
  81. let promiseOrValue; // Execute query
  82. try {
  83. promiseOrValue = config.fn();
  84. } catch (error) {
  85. promiseOrValue = Promise.reject(error);
  86. }
  87. Promise.resolve(promiseOrValue).then(resolve).catch(error => {
  88. var _config$retry, _config$retryDelay;
  89. // Stop if the fetch is already resolved
  90. if (isResolved) {
  91. return;
  92. } // Do we need to retry the request?
  93. const retry = (_config$retry = config.retry) != null ? _config$retry : 3;
  94. const retryDelay = (_config$retryDelay = config.retryDelay) != null ? _config$retryDelay : defaultRetryDelay;
  95. const delay = typeof retryDelay === 'function' ? retryDelay(failureCount, error) : retryDelay;
  96. const shouldRetry = retry === true || typeof retry === 'number' && failureCount < retry || typeof retry === 'function' && retry(failureCount, error);
  97. if (isRetryCancelled || !shouldRetry) {
  98. // We are done if the query does not need to be retried
  99. reject(error);
  100. return;
  101. }
  102. failureCount++; // Notify on fail
  103. config.onFail == null ? void 0 : config.onFail(failureCount, error); // Delay
  104. sleep(delay) // Pause if the document is not visible or when the device is offline
  105. .then(() => {
  106. if (shouldPause()) {
  107. return pause();
  108. }
  109. return;
  110. }).then(() => {
  111. if (isRetryCancelled) {
  112. reject(error);
  113. } else {
  114. run();
  115. }
  116. });
  117. });
  118. }; // Start loop
  119. if (canFetch(config.networkMode)) {
  120. run();
  121. } else {
  122. pause().then(run);
  123. }
  124. return {
  125. promise,
  126. cancel,
  127. continue: () => {
  128. const didContinue = continueFn == null ? void 0 : continueFn();
  129. return didContinue ? promise : Promise.resolve();
  130. },
  131. cancelRetry,
  132. continueRetry
  133. };
  134. }
  135. export { CancelledError, canFetch, createRetryer, isCancelledError };
  136. //# sourceMappingURL=retryer.esm.js.map