()
| 148 | |
| 149 | // Create loop function |
| 150 | const run = () => { |
| 151 | // Do nothing if already resolved |
| 152 | if (isResolved()) { |
| 153 | return |
| 154 | } |
| 155 | |
| 156 | let promiseOrValue: any |
| 157 | |
| 158 | // we can re-use config.initialPromise on the first call of run() |
| 159 | const initialPromise = |
| 160 | failureCount === 0 ? config.initialPromise : undefined |
| 161 | |
| 162 | // Execute query |
| 163 | try { |
| 164 | promiseOrValue = initialPromise ?? config.fn() |
| 165 | } catch (error) { |
| 166 | promiseOrValue = Promise.reject(error) |
| 167 | } |
| 168 | |
| 169 | Promise.resolve(promiseOrValue) |
| 170 | .then(resolve) |
| 171 | .catch((error) => { |
| 172 | // Stop if the fetch is already resolved |
| 173 | if (isResolved()) { |
| 174 | return |
| 175 | } |
| 176 | |
| 177 | // Do we need to retry the request? |
| 178 | const retry = config.retry ?? (environmentManager.isServer() ? 0 : 3) |
| 179 | const retryDelay = config.retryDelay ?? defaultRetryDelay |
| 180 | const delay = |
| 181 | typeof retryDelay === 'function' |
| 182 | ? retryDelay(failureCount, error) |
| 183 | : retryDelay |
| 184 | const shouldRetry = |
| 185 | retry === true || |
| 186 | (typeof retry === 'number' && failureCount < retry) || |
| 187 | (typeof retry === 'function' && retry(failureCount, error)) |
| 188 | |
| 189 | if (isRetryCancelled || !shouldRetry) { |
| 190 | // We are done if the query does not need to be retried |
| 191 | reject(error) |
| 192 | return |
| 193 | } |
| 194 | |
| 195 | failureCount++ |
| 196 | |
| 197 | // Notify on fail |
| 198 | config.onFail?.(failureCount, error) |
| 199 | |
| 200 | // Delay |
| 201 | sleep(delay) |
| 202 | // Pause if the document is not visible or when the device is offline |
| 203 | .then(() => { |
| 204 | return canContinue() ? undefined : pause() |
| 205 | }) |
| 206 | .then(() => { |
| 207 | if (isRetryCancelled) { |
no test coverage detected