From bd3454305d0afc1af2f0fb2b1cc73e6524e74c24 Mon Sep 17 00:00:00 2001 From: Peter Ju Date: Fri, 12 Feb 2021 00:04:40 -0500 Subject: [PATCH] Retry on network errors in Firefox and Safari --- index.d.ts | 4 ++-- index.js | 12 ++++++++++-- readme.md | 3 ++- 3 files changed, 14 insertions(+), 5 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..0e044ac 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(); @@ -16,7 +22,7 @@ class AbortError extends Error { this.name = 'AbortError'; this.message = message; } -} +}; const decorateErrorWithCounts = (error, attemptNumber, options) => { // Minus 1 from attemptNumber because the first attempt does not count as a retry @@ -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/readme.md b/readme.md index 9a02542..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