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

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
简介: axios取消请求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接口是上个页面的,还没返回结果,切换路由后,请求被取消。

目录
相关文章
|
10天前
|
存储 缓存 算法
HashMap深度解析:从原理到实战
HashMap,作为Java集合框架中的一个核心组件,以其高效的键值对存储和检索机制,在软件开发中扮演着举足轻重的角色。作为一名资深的AI工程师,深入理解HashMap的原理、历史、业务场景以及实战应用,对于提升数据处理和算法实现的效率至关重要。本文将通过手绘结构图、流程图,结合Java代码示例,全方位解析HashMap,帮助读者从理论到实践全面掌握这一关键技术。
48 13
|
28天前
|
运维 持续交付 云计算
深入解析云计算中的微服务架构:原理、优势与实践
深入解析云计算中的微服务架构:原理、优势与实践
64 1
|
10天前
|
JSON Shell Linux
dockerfile 用法全解析
Dockerfile指令简介:`FROM`基于Alpine镜像;`WORKDIR`设置工作目录;`COPY`复制文件;`ADD`支持URL;`RUN`运行命令;`CMD`容器启动时执行;`ENTRYPOINT`与`CMD`组合执行;`EXPOSE`声明端口;`VOLUME`映射文件;`ENV`设置环境变量;`ARG`构建参数;`LABEL`元数据;`ONBUILD`触发命令;`STOPSIGNAL`停止信号;`HEALTHCHECK`健康检查;`SHELL`默认Shell。Alpine仅5M,小巧高效。
40 4
dockerfile 用法全解析
|
4天前
|
网络协议 安全 网络安全
探索网络模型与协议:从OSI到HTTPs的原理解析
OSI七层网络模型和TCP/IP四层模型是理解和设计计算机网络的框架。OSI模型包括物理层、数据链路层、网络层、传输层、会话层、表示层和应用层,而TCP/IP模型则简化为链路层、网络层、传输层和 HTTPS协议基于HTTP并通过TLS/SSL加密数据,确保安全传输。其连接过程涉及TCP三次握手、SSL证书验证、对称密钥交换等步骤,以保障通信的安全性和完整性。数字信封技术使用非对称加密和数字证书确保数据的机密性和身份认证。 浏览器通过Https访问网站的过程包括输入网址、DNS解析、建立TCP连接、发送HTTPS请求、接收响应、验证证书和解析网页内容等步骤,确保用户与服务器之间的安全通信。
34 1
|
8天前
|
安全 编译器 Linux
深入解析与防范:基于缓冲区溢出的FTP服务器攻击及调用计算器示例
本文深入解析了利用缓冲区溢出漏洞对FTP服务器进行远程攻击的技术,通过分析FreeFlow FTP 1.75版本的漏洞,展示了如何通过构造过长的用户名触发缓冲区溢出并调用计算器(`calc.exe`)。文章详细介绍了攻击原理、关键代码组件及其实现步骤,并提出了有效的防范措施,如输入验证、编译器保护和安全编程语言的选择,以保障系统的安全性。环境搭建基于Windows XP SP3和Kali Linux,使用Metasploit Framework进行攻击演示。请注意,此内容仅用于教育和研究目的。
33 4
|
25天前
|
XML JSON JavaScript
HttpGet 请求的响应处理:获取和解析数据
HttpGet 请求的响应处理:获取和解析数据
|
28天前
|
前端开发 Java 开发者
Spring MVC中的请求映射:@RequestMapping注解深度解析
在Spring MVC框架中,`@RequestMapping`注解是实现请求映射的关键,它将HTTP请求映射到相应的处理器方法上。本文将深入探讨`@RequestMapping`注解的工作原理、使用方法以及最佳实践,为开发者提供一份详尽的技术干货。
108 2
|
29天前
|
存储 供应链 算法
深入解析区块链技术的核心原理与应用前景
深入解析区块链技术的核心原理与应用前景
56 0
|
1月前
|
JavaScript 前端开发 API
Vue.js响应式原理深度解析:从Vue 2到Vue 3的演进
Vue.js响应式原理深度解析:从Vue 2到Vue 3的演进
58 0
|
2月前
|
资源调度 JavaScript

热门文章

最新文章

推荐镜像

更多