阅读 162

axios之cancelToken取消多次重复请求

一、我们为什么需要取消?

我们常见的业务场景有,用户频繁点击数据提交,用户频繁的切换数据量大的表格,在网络较差的环境下,会出现一些异常的情况,当然,各类UI库提供的loading状态可以帮我们解决以上烦恼,以及可以通过防抖解决部分问题,但是我们今天从另一个方面,使用axios的cancelToken取消上次重复的请求。

二、我们怎样取消?

先看一下aixos官方文档的cancelToken的代码

方法1:可以使用 CancelToken.source 工厂方法创建 cancel token,像这样:

const CancelToken = axios.CancelToken; const source = CancelToken.source(); axios.get('/user/12345', {   cancelToken: source.token }).catch(function(thrown) {   if (axios.isCancel(thrown)) {     console.log('Request canceled', thrown.message);   } else {      // 处理错误   } }); axios.post('/user/12345', {   name: 'new name' }, {   cancelToken: source.token }) // 取消请求(message 参数是可选的) source.cancel('Operation canceled by the user.'); 复制代码

方法2:还可以通过传递一个 executor 函数到 CancelToken 的构造函数来创建 cancel token:

const CancelToken = axios.CancelToken; let cancel; axios.get('/user/12345', {   cancelToken: new CancelToken(function executor(c) {     // executor 函数接收一个 cancel 函数作为参数     cancel = c;   }) }); // cancel the request cancel(); 复制代码

如何在我们项目中使用呢?

我们项目中,更常用的做法是在拦截器interceptors中使用。

当然,我们需要先定义一个map对象用于存储相关值(map为es6新增对象,如果你对es6不了解,请查阅阮一峰的ECMAScript 6 入门

// 用于存储pending的请求(处理多条相同请求) const pendingRequest = new Map() 复制代码

其次,需要封装一些辅助类的函数

  • generateRequestKey 将重复的请求生成一个唯一的key

import qs from 'qs' // 生成request的唯一key const generateRequestKey = (config = {}) => {   // 通过url,method,params,data生成唯一key,用于判断是否重复请求   // params为get请求参数,data为post请求参数   const { url, method, params, data } = config   return [url, method, qs.stringify(params), qs.stringify(data)].join('&') } 复制代码

  • addPendingRequest将重复的请求,保存到到pendingRequest

// addPendingRequest 将重复请求添加到pendingRequest中 const addPendingRequest = (config) => {   const key = generateRequestKey(config)   if (!pendingRequest.has(key)) { //判断pendingRequest中是否存在key     config.cancelToken = new axios.CancelToken(cancel => {       pendingRequest.set(key, cancel) //将key和cancel以键值对的方式保存     })   } } 复制代码

  • 将重复的请求取消,并在pendingRequest中删除

// removePendingRequest 取消重复请求 const removePendingRequest = (config) => {   const key = generateRequestKey(config)   if (pendingRequest.has(key)) { //判断pendingRequest中是否存在key     const cancelToken = pendingRequest.get(key)     cancelToken(key) // 取消之前发送的请求     pendingRequest.delete(key)// 请求对象中删除requestKey   } } 复制代码

完整代码

import axios from 'axios' import qs from 'qs' // 用于存储pending的请求(处理多条相同请求) const pendingRequest = new Map() // 生成request的唯一key const generateRequestKey = (config = {}) => {   // 通过url,method,params,data生成唯一key,用于判断是否重复请求   // params为get请求参数,data为post请求参数   const { url, method, params, data } = config   return [url, method, qs.stringify(params), qs.stringify(data)].join('&') } // 将重复请求添加到pendingRequest中 const addPendingRequest = (config) => {   const key = generateRequestKey(config)   if (!pendingRequest.has(key)) {     config.cancelToken = new axios.CancelToken(cancel => {       pendingRequest.set(key, cancel)     })   } } // 取消重复请求 const removePendingRequest = (config) => {   const key = generateRequestKey(config)   if (pendingRequest.has(key)) {     const cancelToken = pendingRequest.get(key)     cancelToken(key) // 取消之前发送的请求     pendingRequest.delete(key)// 请求对象中删除requestKey   } } // 请求拦截器 service.interceptors.request.use(   config => {     // 处理重复请求     removePendingRequest(config)     addPendingRequest(config)     return config   },   error => {     // 处理请求错误     return Promise.reject(error)   } ) // 响应拦截器 service.interceptors.response.use(   response => {     // 移除重复请求     removePendingRequest(response.config)          return res   },   error => {     // 异常情况console,方便排查问题     console.log('error', error)     // 移除重复请求     removePendingRequest(error.config || {})          return Promise.reject(error)   } ) 复制代码

三、结尾

代码中如有需要更正和修改的地方,欢迎评论留言,我也会积极回复。


作者:杨小在
链接:https://juejin.cn/post/7025884912141991972

文章分类
后端
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐