如何使用axios重试5xx请求

ibrsph3r  于 2022-11-05  发布在  iOS
关注(0)|答案(8)|浏览(246)

我想使用axios重试5xx请求。我的主请求在try catch块中间。我使用axios-retry库自动重试3次。
我正在使用的url会故意抛出一个503。然而,请求没有被重试,而是被我的catch块捕获。

axiosRetry(axios, {
  retries: 3
});

let result;

const url = "https://httpstat.us/503";
const requestOptions = {
  url,
  method: "get",
  headers: {
  },
  data: {},
};

try {

  result = await axios(requestOptions);

} catch (err) {
  throw new Error("Failed to retry")
}

}
return result;
8i9zcol2

8i9zcol21#

axios-retry使用axios拦截器来重试HTTP请求。它在then或catch处理请求或响应之前拦截它们。下面是工作代码片段。

const axios = require('axios');
const axiosRetry = require('axios-retry');

axiosRetry(axios, {
    retries: 3, // number of retries
    retryDelay: (retryCount) => {
        console.log(`retry attempt: ${retryCount}`);
        return retryCount * 2000; // time interval between retries
    },
    retryCondition: (error) => {
        // if retry condition is not specified, by default idempotent requests are retried
        return error.response.status === 503;
    },
});

async function makeHTTPCall() {
    const response = await axios({
        method: 'GET',
        url: 'https://httpstat.us/503',
    }).catch((err) => {
        if (err.response.status !== 200) {
            throw new Error(`API call failed with status code: ${err.response.status} after 3 retry attempts`);
        }
    });
}

makeHTTPCall();
vwoqyblh

vwoqyblh2#

使用retry

const retry = require('retry');

const operation = retry.operation({
  retries: 5,
  factor: 3,
  minTimeout: 1 * 1000,
  maxTimeout: 60 * 1000,
  randomize: true,
});

operation.attempt(async (currentAttempt) => {
  console.log('sending request: ', currentAttempt, ' attempt');
  try {

    await axios.put(...);

  } catch (e) {
    if (operation.retry(e)) { return; }
  }
});
brjng4g3

brjng4g33#

你可以用axios.interceptors.response.use来做这个。当你遇到错误的时候,你可以用resolve递归返回axios请求。然后你可以自己定义条件,每当你想重试的时候。这是一个简单的axios重试版本,这也是axios-retry做的概念。

const axios = require("axios")
/**
 * 
 * @param {import("axios").AxiosInstance} axios 
 * @param {Object} options 
 * @param {number} options.retry_time
 * @param {number} options.retry_status_code
 */
const retryWrapper = (axios, options) => {
    const max_time = options.retry_time;
    const retry_status_code = options.retry_status_code;
    let counter = 0;
    axios.interceptors.response.use(null, (error) => {
        /**@type {import("axios").AxiosRequestConfig} */
        const config = error.config
        // you could defined status you want to retry, such as 503
        // if (counter < max_time && error.response.status === retry_status_code) {
        if (counter < max_time) {
            counter++
            return new Promise((resolve) => {
                resolve(axios(config))
            })
        }
        return Promise.reject(error)
    })
}

async function main () {
    retryWrapper(axios, {retry_time: 3})
    const result = await axios.get("https://api.ipify.org?format=json")
    console.log(result.data);
}

main()

我还做了一个演示版本来模拟最后一个请求是成功的,但是前面的请求全部失败.我定义了status_code:404我想重试,并设置3次重试。

const axios = require("axios")
/**
 * 
 * @param {import("axios").AxiosInstance} axios 
 * @param {Object} options 
 * @param {number} options.retry_time
 * @param {number} options.retry_status_code
 */
const retryWrapper = (axios, options) => {
    const max_time = options.retry_time;
    const retry_status_code = options.retry_status_code;
    let counter = 0;
    axios.interceptors.response.use(null, (error) => {
        console.log("==================");
        console.log(`Counter: ${counter}`);
        console.log("Error: ", error.response.statusText);
        console.log("==================");

        /**@type {import("axios").AxiosRequestConfig} */
        const config = error.config
        if (counter < max_time && error.response.status === retry_status_code) {
            counter++
            return new Promise((resolve) => {
                resolve(axios(config))
            })
        }
        // ===== this is mock final one is a successful request, you could delete one in usage.
        if (counter === max_time && error.response.status === retry_status_code) {
            config.url = "https://api.ipify.org?format=json"
            return new Promise((resolve) => {
                resolve(axios(config))
            })
        }
        return Promise.reject(error)
    })
}

async function main () {
    retryWrapper(axios, {retry_time: 3, retry_status_code: 404})
    const result = await axios.get("http://google.com/not_exist")
    console.log(result.data);
}

main()

您将看到以下日志打印消息。

==================
Counter: 0
Error:  Not Found
==================
==================
Counter: 1
Error:  Not Found
==================
==================
Counter: 2
Error:  Not Found
==================
==================
Counter: 3
Error:  Not Found
==================
{ ip: 'x.x.x.x' }
frebpwbc

frebpwbc4#

您可以使用axios拦截器来拦截响应并重试请求。
您可以在thencatch处理请求或响应之前将其截获。
请参阅axios拦截器
有两个流行的包已经利用axios拦截器来实现这一点:

这里有一个NPM compare链接,可以帮助您在这两者之间做出选择

ef1yzkbh

ef1yzkbh5#

正在更新Andrien应答以防止进程泄漏。我们应该在请求成功后停止循环,但忘记了添加增量,因此这意味着它永远不会停止循环。这将仅在请求失败时重试,最大值为3。您可以根据您的首选值更改maxRetries来增加该值。

new Promise(async (resolve, reject) => {
  let retries = 0;
  let success = false;
  const maxRetries = 3;

  while (retries < maxRetries && !success) {
    try {
      const response = await axios(options);
      success = true
      resolve(response.data);
    } catch (err) {
      const status = err?.response?.status || 500;
      console.log(`Error Status: ${status}`);
    }
    retries++
  }
  console.log(`Too many request retries.`);
  reject()
})

有关更多详细信息,请查看while循环的文档:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/while

ryoqjall

ryoqjall6#

被接受的解决方案将强制所有失败的HTTP请求(使用axios)重试。
一个解决方案是为特定的HTTP调用创建一个新的axios示例,并为其定义重试策略:

import axios from 'axios'
import axiosRetry from 'axios-retry'

async function call(){
  const client = axios.create()
  axiosRetry(client, { retries: 4, /* ...more options */ })

  const response = client.get("https://www.google.com")
}

call()

``
wixjitnu

wixjitnu7#

它使用了Junius L.引用的retry库,但我将它 Package 在一个promise中。它将在超时时拒绝,并在成功后解析。

const retry = require('retry');
const sendWithRetry = axiosCall => new Promise((resolve, reject) => {
    const operation = retry.operation({
        retries: 5,
        factor: 3,
        minTimeout: 1 * 1000,
        maxTimeout: 60 * 1000,
        randomize: true,
    });
    operation.attempt(async (currentAttemptNumber) => {
        try {
            await axiosCall;
        } catch (e) {
            if (operation.retry(e)) { return; }
            resolve();
        }
    }, reject);
});
s8vozzvw

s8vozzvw8#

您可以通过不使用其他库来实现此目的。

new Promise(async (resolve, reject) => {
  let retries = 0;
  const maxRetries = 3;

  while (retries < maxRetries) {
    try {
      const response = await axios(options);
      break;
      resolve(response.data);
    } catch (err) {
      const status = err?.response?.status || 500;
      console.log(`Error Status: ${status}`);
      retries++
    }
  }
  console.log(`Too many request retries.`);
  reject()
})

相关问题