【问题标题】:Axios interceptor retry http request when status is 200 and data is empty状态为200且数据为空时axios拦截器重试http请求
【发布时间】:2019-09-15 19:37:30
【问题描述】:

我正在短暂轮询端点,直到一些数据准备好我想重试请求最多 10 次。

当数据没有准备好时,我会收到一个 200 的空数组。

当数据准备好时,我会收到一个 200 的非空数组。

我使用以下库 https://github.com/axios/axios https://github.com/softonic/axios-retry

 try {

   const axiosInstance = axios.create();

   axiosInstance.interceptors.response.use((response) => {

     if (response.data.metrics.length === 0) {
       const error = new Error("Metrics Not Ready");
       return Promise.reject(error);

     }
     return response;
   }, (error) => {
     return Promise.reject(error);
   });

   axiosRetry(axiosInstance, {
     retries: 10,
     retryCondition: (error) => {
       console.log("RETRY CONDITION", error);
     },
   });

   const metrics = await axiosInstance(options);

 } catch (error) {
   console.log(error);
 }

我创建了一个 axios 拦截器来检查数组的长度,如果它为 0,我会抛出错误。但是,这不会被 axiosRetry 捕获,此时我想重试请求。相反,它被 try catch 块捕获并结束。

【问题讨论】:

  • 或者是否有办法拦截响应并在数据不存在时覆盖它,以便 axiosRetry 知道重试。

标签: node.js reactjs http axios


【解决方案1】:

你不需要 axios-retry,你只需要 axios 及其响应拦截器,步骤如下:

  1. 检查数据是否为空。如果是,则抛出axios.Cancel 错误。这将取消请求,调用错误处理程序而不是成功处理程序。
  2. 在错误处理程序中,如果我们没有超过最大重试次数(在您的情况下为 10),则重新发送 HTTP 请求。
  3. 继续运行第 1 步和第 2 步,直到我们获得数据或重试 10 次。

代码如下所示:

const axios = require('axios');

const MAX_RETRY = 10;
let currentRetry = 0;

function successHandler() {
  console.log('Data is Ready');
}

function errorHandler() {
  if (currentRetry < MAX_RETRY) {
    currentRetry++;
    console.log('Retrying...');
    sendWithRetry();
  } else {
    console.log('Retried several times but still failed');
  }
}

function sendWithRetry() {
  axios.get('http://example.com')
    .then(successHandler).catch(errorHandler);
}

axios.interceptors.response.use(function (response) {
  if (response.data.metrics.length) {
    throw new axios.Cancel('Operation canceled by the user.');
  } else {
    return response;
  }
}, function (error) {
  return Promise.reject(error);
});

sendWithRetry();

对于 axios-retry,很遗憾,当响应状态为 200 OK 时,您无法重试 HTTP 请求,因为 axios-retry 使用 axios.interceptors.response.use 但对“成功响应”没有任何作用。

这里是axios-retry的源文件es/index.js中对应的代码。可以看到响应成功的拦截器是null

export default function axiosRetry(axios, defaultOptions) {
  axios.interceptors.request.use(config => {
    const currentState = getCurrentState(config);
    currentState.lastRequestTime = Date.now();
    return config;
  });

  axios.interceptors.response.use(null, error => {
    const config = error.config;

    // If we have no information to retry the request
    if (!config) {
      return Promise.reject(error);
    }
    ....

【讨论】:

  • 我想将 axios-retry 用于它内置的回退策略。有没有办法用 axios-retry 库做重试?
  • @Kay 不幸的是,我认为没有任何方法可以使用 axios-retry 来实现您的要求。我已经编辑了答案以说明原因。
  • 哦,太糟糕了,我将不得不考虑使用可以在 2xx 上重试的不同库以及退避策略。也许如果您或看到此内容的其他人知道这样的库,您可以推荐它。
  • 嗨,@Kay,正如我在回答中所描述的,您不需要任何新库 :) 您可以实现自己的“重试 2xx”逻辑作为退避。
猜你喜欢
  • 1970-01-01
  • 2019-07-10
  • 2020-02-12
  • 2019-03-12
  • 2022-11-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-20
相关资源
最近更新 更多