首页 > 其他分享 >axios取消请求CancelToken的原理解析及用法示例

axios取消请求CancelToken的原理解析及用法示例

时间:2024-08-19 15:26:11浏览次数:5  
标签:axios 请求 示例 取消 拦截器 config CancelToken

文章目录

一、axios的实例与请求流程

下图是axios实例属性的简图。

在这里插入图片描述

下图是axios的请求流程

在这里插入图片描述

axios的实例上,其实主要就这三个东西:

  • config:配置,比如url、method、params、headers等等
  • interceptors :拦截器,分为请求拦截器和返回拦截器。
  • request:调用xhr或者http请求的方法,参数就是config

二、CancelToken 的作用

Axios 是一个基于 Promise 的 HTTP 客户端,用于在浏览器和 Node.js 中发起 HTTP 请求。除了强大的功能和丰富的配置选项,Axios 还提供了一个实用的特性——CancelToken,它允许我们取消一个或多个正在进行的请求。

在网络应用中,我们经常需要处理一些可能需要取消的请求,比如用户在加载数据时跳转到了其他页面,或者在表单提交前用户点击了取消按钮。在这些场景下,如果能够取消请求,就能避免不必要的资源消耗和更好的用户体验。

三、CancelToken 的实现原理

CancelToken 的工作原理依赖于 Promise 的链式调用和 throw 语句。在 Axios 发起请求时,会检查请求的 cancelToken 属性,如果存在,就将其添加到当前请求的 cancelToken 列表中。

当调用 cancel 方法时,CancelToken 会抛出一个带有特定 message 的 Cancel 对象。这个对象会被 Promise 的 catch 方法捕获,从而触发请求的取消逻辑。

四、取消请求的流程

CancelToken的静态方法CancelToken.source返回了两个东西:分别是token和cancel方法。

在这里插入图片描述

下图是取消请求的流程

在这里插入图片描述

可以看到,流程里,axios分别在请求前、请求中、请求后进行了是否取消的判断。

这也就意味着,当我们在请求拦截器中调用cancel方法,axios会识别到,抛出异常。

五、CancelToken用法

先引用axios.CancelToken,然后调用source()方法,会产生一个token和cancel

const CancelToken = axios.CancelToken;
const source = CancelToken.source();

// get请求示例
axios.get('/user/12345', {
  cancelToken: source.token
}).catch((thrown)=> {
  if (axios.isCancel(thrown)) {
    console.log('Request canceled', thrown.message);
  } else {
    // 处理错误
  }
});

// post请求示例
axios.post('/user/12345', {name: 'new name'}, {cancelToken: source.token});

// 取消请求(message 参数是可选的)
source.cancel('不想请求了');
  • get请求的时候,cancelToken是放在第二个参数里;
  • post的时候,cancelToken是放在第三个参数里。

六、利用拦截器取消请求

先封装一下方法

// 全局变量对象,专门存放所有请求的cancel方法
window.pendingRequest = new Map()

// 生成request的唯一的标识
const generateRequestKey = (config = {}) => {
    // 通过url,method,params,data生成唯一key,用于判断是否重复请求
    // params为get请求参数,data为post请求参数
    const {url,method,params,data} = config
    if (method == 'get') {
        return [url, method, qs.stringify(params)].join('&')
    }
    return [url, method, 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 cancelRepeatRequest = (config) => {
    const key = generateRequestKey(config)
    if (pendingRequest.has(key)) {
        const cancelToken = pendingRequest.get(key)
        cancelToken(key) // 取消之前发送的请求
        pendingRequest.delete(key) // 请求对象中删除requestKey
    }
}
1、axios请求拦截器

在发送请求之前,为每个请求生成一个唯一的标识,这个标识可以根据请求的URL、方法以及所传递的参数等信息生成。

通过使用Axios的请求拦截器,你可以在请求发送前进行检查,如果发现有一个相同标识的请求已经在进行中,就可以使用CancelToken取消前一个请求,或者跳过当前请求。

// 创建axios实例
const httpService = axios.create({});

// request拦截器
httpService.interceptors.request.use(
    config => {
        // 取消重复请求
        cancelRepeatRequest(config)
        // 添加请求到队列
        addPendingRequest(config)
        return config;
    },
    error => {
        return Promise.reject(error);
    }
)
2、axios响应拦截器

响应拦截器可以用来清理已完成或已取消的请求的记录,确保请求映射表只保留活跃的请求。这个机制使得在实际应用中管理和取消重复的请求变得容易。

httpService.interceptors.response.use(
    response => {
        // 取消请求队列中该请求
        cancelRepeatRequest(response .config);
            
        if (response.status == 200) {
            return response;
        } else {
            return Promise.reject(response);
        }
    },
    // 处理处理
    error => {
        // 取消请求队列中该请求
        cancelRepeatRequest(error.config || {})
        return Promise.reject(error);
    }
)

在这里插入图片描述
在这里插入图片描述

这里我同时发送了3次重复的history请求,过滤取消了2次,成功发送了1次。

3、利用路由导航守卫取消请求

当路由切换的时候,在路由钩子里遍历这个数组,调用所有的cancel方法,将上一个页面还未完的请求取消,这样就可以加快页面的加载,避免不必要的等待。

router.beforeEach((to, from, next) => {
  if(pendingRequest){
    pendingRequest.forEach((cancel) => {
      cancel();
    });
    pendingRequest = new Map();
  }
  next();
})  

当路由切换页面的时候,遍历全局数组,将上一个页面的所有请求cancel掉。

在这里插入图片描述

图中history接口是上个页面的,还没返回结果,切换路由后,请求被取消。

标签:axios,请求,示例,取消,拦截器,config,CancelToken
From: https://blog.csdn.net/shanghai597/article/details/141132511

相关文章

  • Node.js使用Axios发起http调用
    axios功能比较多,除了基本get/post调用之外,还支持多个接口并发调用、全局配置、拦截器等功能。笔者这里只介绍简单使用方法。安装npminstallaxiosGET请求:constaxios=require('axios');axios.get('http://api.qingyunke.com/api.php',{params:{key:'fre......
  • Java中ArrayList集合—基础详解(知识点+代码示例)
    ArrayList(集合)ArrayList(集合)ArrayList(集合)10.1ArrayList成员方法10.2集合练习10.2.1添加字符串10.2.2添加数字10.2.3添加学生对象并遍历10.2.4集合概述:集合可以直接存储引用数据类型,不能直接存储基本数据类型,如果要存储基本数据类型,需要将基本数据类型变成对......
  • Sonarqube 自定义规则,部署SonarSource / sonar-java源码中示例规则:docs/java-custom-r
    自定义规则,可以参考sonar-java/docs/CUSTOM_RULES_101.mdat8.0.0.36314·SonarSource/sonar-java·GitHub1、下载一份sonarqube源码,配置好本地的环境,JDK17和mavendocs/java-custom-rules-example示例项目中会有写好的规则;我们可以先尝试将这些写好的规则添加到Sonarqube......
  • Vue3+Axios
    使用Vue3和Axios实现CRUD操作在当今的前端开发中,Vue.js作为一款流行的JavaScript框架,正在被越来越多的开发者所青睐。尤其是Vue3引入了CompositionAPI和更优雅的响应式处理,使得模板编写和状态管理变得更加直观。在这篇博客中,我将带领大家通过一个简单的示例,使用......
  • 基于SpringBoot的停车场管理系统+毕业设计示例参考
    郑重声明:项目经过本地测试,确保可以运行。项目仅供学习和毕业设计参考~1.项目介绍技术栈+工具:SpringBoot+BootStrap+MySQL5.7+IDEA2022+Maven系统功能:系统管理、角色管理、车辆管理、车位管理、停车记录、充值、停车出场等系统角色:管理员、普通用户(可自行设定角......
  • 基于SSM的酒店客房管理系统+毕业设计示例参考
    郑重声明:项目经过本地测试,确保可以运行。项目仅供学习和毕业设计参考~1.项目介绍技术栈+工具:SSM+MySQL+IDEA2022+Maven+JSP系统功能:登录注册、客房预订、公告查看、留言功能、客房管理、入驻管理、退房管理等系统角色:管理员、酒店前台、普通用户2.项目部署创......
  • 使用SSMS操作AdventureWorks 示例数据库
    简介AdventureWorks示例数据库,官方文档:https://learn.microsoft.com/zh-cn/sql/samples/adventureworks-install-configure?view=sql-server-ver16&tabs=ssms 下载备份文件OLTP数据适用于大多数典型的联机事务处理工作负载。数据仓库(DW)数据适用于数据仓库工作负载。轻......
  • vue3 - 详细实现内网使用离线百度地图功能,在vue3中无需网络离线使用百度地图相关功能,
    效果图在vue3、nuxt3项目开发中,完成内网离线使用百度地图详细教程,让vue3网站无需网络就能加载百度地图及相关功能,完整的百度地图离线使用及地图瓦片的下载教程、更新教程等,vue3百度地图内网离线使用显示地图及各种功能,无论js/ts语法都可以使用,详解百度地图离线加载机制及整......
  • 以c primer plus(第六版)为大纲的C语言初学手记,含示例代码及编程练习(第四章)
    //第4章//example4.1//#include<stdio.h>//#include<string.h> //toincludestrlrn()//#defineDENSITY62.4 //todefineaconstant//intmain()//{//   floatweight,volume;//   intsize,letters;//   charname[40]; //todeclareadig......
  • 026、Vue3+TypeScript基础,使用async和await来异步读取axios的网络图片
    01、App.vue代码如下:<template><divclass="app"><h2>App.Vue</h2><Person/></div></template><scriptlang="ts"setupname="App">//JS或TSimportPersonfrom'./......