From d549c5aa69a6db66e1e2563ce18a3e17b6fbe74d Mon Sep 17 00:00:00 2001 From: Peter Ju Date: Fri, 12 Feb 2021 22:09:29 -0500 Subject: [PATCH 1/3] Retry on network errors in Firefox and Safari --- index.d.ts | 4 ++-- index.js | 10 +++++++++- package.json | 2 +- readme.md | 5 +++-- 4 files changed, 15 insertions(+), 6 deletions(-) diff --git a/index.d.ts b/index.d.ts index 138a76e..5b1c8a9 100644 --- a/index.d.ts +++ b/index.d.ts @@ -52,8 +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. 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)." + Does not retry on most `TypeErrors`, with the exception of network errors. This is done on a best case basis as different browsers have different [messages](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch#Checking_that_the_fetch_was_successful) to indicate this. + 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 db5fb9c..a110073 100644 --- a/index.js +++ b/index.js @@ -1,6 +1,12 @@ 'use strict'; const retry = require('retry'); +const networkErrorMsgs = [ + 'Failed to fetch', // Chrome + 'NetworkError when attempting to fetch resource', // Firefox + 'The Internet connection appears to be offline' // Safari +]; + class AbortError extends Error { constructor(message) { super(); @@ -27,6 +33,8 @@ const decorateErrorWithCounts = (error, attemptNumber, options) => { return error; }; +const isNetworkError = errorMessage => networkErrorMsgs.includes(errorMessage); + const pRetry = (input, options) => new Promise((resolve, reject) => { options = { onFailedAttempt: () => {}, @@ -48,7 +56,7 @@ const pRetry = (input, options) => new Promise((resolve, reject) => { if (error instanceof AbortError) { operation.stop(); reject(error.originalError); - } else if (error instanceof TypeError && error.message !== 'Failed to fetch') { + } else if (error instanceof TypeError && !isNetworkError(error.message)) { operation.stop(); reject(error); } else { diff --git a/package.json b/package.json index fbe614f..efd6218 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "p-retry", - "version": "4.2.0", + "version": "4.3.0", "description": "Retry a promise-returning or async function", "license": "MIT", "repository": "sindresorhus/p-retry", diff --git a/readme.md b/readme.md index 1731251..8a7e91c 100644 --- a/readme.md +++ b/readme.md @@ -39,7 +39,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. 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)." +Does not retry on most `TypeErrors`, with the exception of network errors. This is done on a best case basis as different browsers have different [messages](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch#Checking_that_the_fetch_was_successful) to indicate this. See [whatwg/fetch#526 (comment)](https://github.com/whatwg/fetch/issues/526#issuecomment-554604080) + #### input @@ -63,7 +64,7 @@ Callback invoked on each retry. Receives the error thrown by `input` as the firs const run = async () => { const response = await fetch('https://sindresorhus.com/unicorn'); - if (response.status !== 200) { + if (!response.ok) { throw new Error(response.statusText); } From 1c791dcba750d9896c3555a89f9b61dd84e3dc98 Mon Sep 17 00:00:00 2001 From: Sindre Sorhus Date: Mon, 15 Feb 2021 17:55:36 +0700 Subject: [PATCH 2/3] Restore package.json From a8845f7e777ebf2793ed52fc22e116fb71514290 Mon Sep 17 00:00:00 2001 From: Sindre Sorhus Date: Mon, 15 Feb 2021 17:56:39 +0700 Subject: [PATCH 3/3] Update package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index efd6218..fbe614f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "p-retry", - "version": "4.3.0", + "version": "4.2.0", "description": "Retry a promise-returning or async function", "license": "MIT", "repository": "sindresorhus/p-retry",