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