retryer.js 4.5 KB

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