diff --git a/index.d.ts b/index.d.ts index e20b352..138a76e 100644 --- a/index.d.ts +++ b/index.d.ts @@ -52,7 +52,8 @@ declare const pRetry: { /** Returns a `Promise` that is fulfilled when calling `input` returns a fulfilled promise. If calling `input` returns a rejected promise, `input` is called again until the max retries are reached, it then rejects with the last rejection reason. - It doesn't retry on `TypeError` as that's a user error. + It doesn't retry on `TypeError` as that's a user error. The only exclusion to this logic is when `TypeError` is thrown by `fetch`'s API with the message 'Failed to fetch', [which indicates that a request was not successful due to a network error](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch#Checking_that_the_fetch_was_successful). + However, beware that `fetch` may throw `TypeError` with different error messages on different platforms for similar situations. See [whatwg/fetch#526 (comment)](https://github.com/whatwg/fetch/issues/526#issuecomment-554604080)." @param input - Receives the number of attempts as the first argument and is expected to return a `Promise` or any value. @param options - Options are passed to the [`retry`](https://github.com/tim-kos/node-retry#retryoperationoptions) module. diff --git a/index.js b/index.js index d96dd3a..db5fb9c 100644 --- a/index.js +++ b/index.js @@ -48,7 +48,7 @@ const pRetry = (input, options) => new Promise((resolve, reject) => { if (error instanceof AbortError) { operation.stop(); reject(error.originalError); - } else if (error instanceof TypeError) { + } else if (error instanceof TypeError && error.message !== 'Failed to fetch') { operation.stop(); reject(error); } else { diff --git a/readme.md b/readme.md index 302158c..007edd5 100644 --- a/readme.md +++ b/readme.md @@ -38,7 +38,8 @@ const run = async () => { Returns a `Promise` that is fulfilled when calling `input` returns a fulfilled promise. If calling `input` returns a rejected promise, `input` is called again until the maximum number of retries is reached. It then rejects with the last rejection reason. -It doesn't retry on `TypeError` as that's a user error. + +It doesn't retry on `TypeError` as that's a user error. The only exclusion to this logic is when `TypeError` is thrown by `fetch`'s API with the message 'Failed to fetch', [which indicates that a request was not successful due to a network error](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch#Checking_that_the_fetch_was_successful). However, beware that `fetch` may throw `TypeError` with different error messages on different platforms for similar situations. See [whatwg/fetch#526 (comment)](https://github.com/whatwg/fetch/issues/526#issuecomment-554604080)." #### input diff --git a/test.js b/test.js index 20c2e74..fdd2a00 100644 --- a/test.js +++ b/test.js @@ -48,6 +48,20 @@ test('no retry on TypeError', async t => { t.is(i, 1); }); +test('retry on TypeError - failed to fetch', async t => { + const typeErrorFixture = new TypeError('Failed to fetch'); + let index = 0; + + const returnValue = await pRetry(async attemptNumber => { + await delay(40); + index++; + return attemptNumber === 3 ? fixture : Promise.reject(typeErrorFixture); + }); + + t.is(returnValue, fixture); + t.is(index, 3); +}); + test('AbortError - string', t => { const error = new pRetry.AbortError('fixture').originalError; t.is(error.constructor.name, 'Error');