谈谈Axios如何取消请求

Axios: 目前使用较多,支持全局配置,请求,响应的拦截器,取消请求等操作.

场景: 当我们在网站上使用上传功能上传一个图片或者视频时,突然遇到网路不好或者服务器挂了,那么此时用于展示上传的 loading 就会卡死在这,毕竟服务器挂了以后,是得不到响应的.

解决方法1: 使用axios全局配置一个超时时间,具体见官方文档.
解决方法2: 添加一个取消当前请求的按钮或者一个关闭图标

具体如下(基于vue)
Parent组件中使用两个组件,一个是Loading组件,一个是Child组件
Child组件: 发送请求获取数据(上传文件同样),将发送请求的动作的令牌,通知父组件 Parent, 父组件Parent将令牌传递给Loading组件.这就保证了Child组件与Loading组件使用的是同一个令牌,也就是所操作的是同一个请求.
令牌包含一个代表当前请求的token属性,还有一个用来取消当前请求的cancel方法.

代码实现如下:
js文件主入口需要配置axios,如IE中不支持Promise,请使用babel-polyfill,可自行百度
javascript 代码

import axios from 'axios';

Vue.prototype.$http = axios;

Parent组件
javascript 代码

<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
    <Child @cancelButton="handleCancel"></Child>
    <Loading :source="source"></Loading>
  </div>
</template>

<script>
import Child from './Child';
import Loading from './Loading';
export default {
  name: 'HelloWorld',
  data () {
    return {
      msg: 'Welcome to Your Vue.js App',
      source: null
    }
  },
  components: {
    Child,
    Loading
  },
  methods: {
    handleCancel(source) {
      this.source = source; //获取到Child组件传递过来的令牌,然后将令牌通过props的形式传递给Loading组件
    }
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h1, h2 {
  font-weight: normal;
}
ul {
  list-style-type: none;
  padding: 0;
}
li {
  display: inline-block;
  margin: 0 10px;
}
a {
  color: #42b983;
}
</style>

Child组件
javascript 代码

<template>
  <div class="child">
      111
      <button @click="getData">获取数据</button>
  </div>
</template>

<script>
export default {
  data() {
    return {};
  },
  methods: {
    getData() {
      let _this = this;
      let CancelToken = _this.$http.CancelToken;
      let source = CancelToken.source();
      _this.$emit("cancelButton", source); //把该请求的令牌传递给父组件
      _this.$http
        .get("http://jsonplaceholder.typicode.com/comments", {
          cancelToken: source.token
        })
        .then(function(response) {
          console.log(response);
        })
        .catch(function(msg) {
          console.log(msg);
          _this.$emit('cancelButton', null);
        });
    }
  },
  mounted() {}
};
</script>

<style>
.child {
  margin: 50px;
}
</style>

Loading组件
javascript 代码

<template>
  <div class="loading">
      222
      <button v-show="source" @click="handleCancel">取消请求</button>
  </div>
</template>

<script>
export default {
  data() {
      return {

      }
  },
  props: [
      'source'
  ],
  methods: {
      handleCancel() {
          console.log(this.source);
          this.source.cancel('123');
          //一旦取消当前请求操作,cancel方法中的参数,将会被Child组件中 catch 所捕获,当然全局的响应拦截器也会捕获到该错误,该错误对象包含一个message属性,而这个属性的值正是cancel方法中所传递的参数
      }
  },
  mounted() {
      console.log(this.source);
  }
}
</script>
<think>好的,我现在需要解决用户关于Axios超时后重新请求的问题。用户希望找到实现方法或者解决方案。首先,我得回忆一下Axios的基本用法和配置,特别是如何处理超时以及重试机制。 首先,Axios本身有一个timeout配置项,可以设置请求超时的时间。当请求超过这个时间没有响应,就会触发错误。这时候,需要捕获这个错误,并判断是否是超时导致的,然后进行重试。所以,关键点在于错误处理和重试逻辑的实现。 接下来,我需要考虑如何实现重试。通常的做法是使用拦截器,在响应拦截器中检查错误类型,如果是超时错误,就重新发送请求。这里可能需要一个计数器来记录重试的次数,避免无限重试。比如设置最大重试次数为3次,每次重试前等待一段时间,可以使用setTimeout函数。 然后,用户提供的引用中有提到引用[2]关于作业链的内容,其中提到一个作业不成功后续不会进行。这可能类似于重试机制中的顺序执行,但需要确保每次重试都是独立的。不过Axios的拦截器更适合在这里使用,而不是作业链。 另外,引用[4]中提到了观察者模式监听数据结果,这可能与在Vue或React中处理响应有关,但核心还是错误处理和重试逻辑。 需要注意的点包括: 1. 使用Axios的拦截器来捕获请求错误。 2. 判断错误是否为超时(error.code === 'ECONNABORTED' 或者 error.message.includes('timeout'))。 3. 维护一个重试计数器,控制重试次数。 4. 在重试之间添加延迟,可以使用指数退避策略,比如每次等待时间逐渐增加。 5. 确保重试的请求配置正确,尤其是可能需要重新生成config中的某些参数,比如取消令牌。 可能的代码结构如下: - 创建一个axios实例,配置timeout。 - 使用请求拦截器和响应拦截器。 - 在响应拦截器的错误处理中,检查是否为超时错误,并判断重试次数。 - 使用async/await或者Promise来处理延迟和重试。 还需要考虑一些边界情况,比如请求是否幂等,是否允许重复提交(例如POST请求),但用户的问题主要集中在超时重试,可能默认处理GET请求或者幂等的请求。 最后,给出示例代码,并解释每一步的作用,确保用户能够理解如何实现。同时,生成相关问题,帮助用户深入理解。</think>### Axios超时重试实现方法 Axios实现超时后自动重请求主要通过**拦截器+计数器+延迟机制**实现,具体步骤分为四个部分: #### 一、基础配置 ```javascript const axiosInstance = axios.create({ timeout: 5000, // 设置基础超时时间 retry: 3, // 最大重试次数 retryDelay: 1000 // 重试间隔 }); ``` #### 二、拦截器实现 ```javascript // 响应拦截器 axiosInstance.interceptors.response.use(null, async (error) => { const config = error.config; // 1. 识别超时错误 if (error.code === 'ECONNABORTED' && error.message.includes('timeout') && config && !config.__retryCount) { config.__retryCount = config.__retryCount || 0; // 2. 控制重试次数 if (config.__retryCount >= config.retry) { return Promise.reject(error); } config.__retryCount += 1; // 3. 创建新的Promise延迟 const delay = new Promise(resolve => { setTimeout(() => resolve(), config.retryDelay); }); // 4. 重新发送请求 return delay.then(() => axiosInstance(config)); } return Promise.reject(error); }); ``` #### 三、请求示例 ```javascript axiosInstance.get('/api/data') .then(response => console.log(response)) .catch(error => console.error('最终失败:', error)); ``` #### 四、高级优化方案 1. **动态退避策略**:使用指数退避算法 ```javascript retryDelay: (retryCount) => { return 1000 * Math.pow(2, retryCount); } ``` 2. **特定请求跳过重试** ```javascript // 在请求配置中添加标记 axios.get('/api/payment', { retry: false }) ``` 3. **重试状态通知** ```javascript config.onRetry = (retryCount) => { console.log(`第${retryCount}次重试`); } ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

RI Code

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值