当前位置: 首页 > news >正文

Axios取消请求,以及全局取消请求封装

前提准备

首先编写一个测试接口,模拟接口延迟返回,请求5秒后再返回结果

使用 node + koa 来实现

const Router = require("koa-router");
const router = new Router();router.get("/getLongData", async (ctx, res) => {// 获取get请求的参数// console.log(ctx.query);await new Promise((resolve) => {setTimeout(() => {resolve();}, 5000);});ctx.body = {code: 200,message: "请求成功!",};
});module.exports = router;

AbortController

使用 AbortController

AbortController 是一个浏览器提供的 API,用于取消正在进行的异步操作,如 Fetch 请求或 Axios 请求。你可以创建一个 AbortController 实例,并在 Axios 请求配置中通过 signal 属性传递它。

import axios from 'axios';const controller = new AbortController();axios.get('/foo/bar', {signal: controller.signal
}).then(response => {// 处理响应
}).catch(error => {if (error.name === 'AbortError') {console.log('请求被取消');} else {console.error('发生了一个错误:', error);}
});// 取消请求
controller.abort();

CancelToken

CancelToken 是 Axios 自带的一个类,用于实现请求取消功能。你需要创建一个 CancelToken 实例,并在请求配置中通过 cancelToken 属性传递它。

import axios from 'axios';
import CancelToken from 'axios/cancelToken';let cancel;// 发起请求
axios.get('/foo/bar', {cancelToken: new CancelToken(c => cancel = c)
}).then(response => {// 处理响应
}).catch(error => {if (axios.isCancel(error)) {console.log('请求被取消');} else {console.error('发生了一个错误:', error);}
});// 取消请求
if (cancel) {cancel('取消请求的原因');
}

全局取消请求封装

新建一个 globalCancelToken.js

// 最新的一个请求
let cancel = null// 所有请求
let cancelTokenList = []function setToken(cancelToken) {cancel = cancelTokencancelTokenList.push(cancelToken)
}function cancelToken() {cancel && cancel()cancelTokenList.pop()
}function clearAllToken() {while (cancelTokenList.length > 0) {let cancel = cancelTokenList.pop()console.log(cancel, 'cancel')cancel && cancel()}
}export {setToken,cancelToken,clearAllToken,
}

这个文件中定义了一个变量,一个数组,cancelTokenList 用于存放每一次请求所对应的 cancelToken

在请求拦截器中添加取消请求的配置,相应拦截器中判断错误类型是否为取消请求

import { setToken } from '@/utils/globalCancelToken.js'// 创建axios实例
const service = axios.create({// axios中请求配置有baseURL选项,表示请求URL公共部分baseURL: import.meta.env.VITE_APP_BASE_API,// 超时timeout: 100000,
})// request拦截器
service.interceptors.request.use(config => {// 省略其他配置....// 添加可取消请求配置config.cancelToken = new axios.CancelToken(c => setToken(c))return config
}, error => {console.log(error)Promise.reject(error)
})// 响应拦截器
service.interceptors.response.use(res => {// 未设置状态码则默认成功状态const code = res.data.code || '0'// 获取错误信息const msg = errorCode[code] || res.data.message || errorCode['default']// 二进制数据则直接返回if (res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer') {return res.data}if (code === 401 || code === '10006') {if (!isRelogin.show) {isRelogin.show = trueElMessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', {confirmButtonText: '重新登录',cancelButtonText: '取消',type: 'warning',}).then(() => {isRelogin.show = falseuseUserStore().logOut().then(() => {location.href = '/index'})}).catch(() => {isRelogin.show = false})}return Promise.reject('无效的会话,或者会话已过期,请重新登录。')} else if (code === 500) {ElMessage({ message: msg, type: 'error' })return Promise.reject(new Error(msg))} else if (code !== '0') {ElMessage({ message: msg, type: 'error' })return Promise.reject('error')} else {return Promise.resolve(res.data)}},error => {if (error.name === 'CanceledError') {console.log('请求已取消')return Promise.reject('请求已取消')}ElMessage({ message: message, type: 'error', duration: 5 * 1000 })return Promise.reject(error)},
)

编写测试页面

<template><div><el-button type='primary' @click='send'>发起请求</el-button><el-button type='warning' @click='cancelSend'>取消最近一次请求</el-button><el-button type='warning' @click='cancelAllSend'>取消所有请求</el-button></div>
</template><script setup>
import { testAxiosServer } from '@/api/testApi.js'
import { cancelToken, clearAllToken } from '@/utils/globalCancelToken.js'function send() {testAxiosServer().then(res => {console.log(res)})
}function cancelSend() {cancelToken()
}function cancelAllSend() {clearAllToken()
}// 组件销毁前取消所有未完成的请求
onUnmounted(() => {clearAllToken()
})
</script>

axios

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 瑞_RabbitMQ_初识MQ
  • [Web安全架构] HTTP协议
  • 【JVM】深入JIT优化机制
  • AI安全新纪元:智能体驱动的网络安全新范式
  • 【JavaEE初阶】文件操作和IO
  • 【基础篇】数据结构
  • 无缝融入,即刻智能[一]:Dify-LLM大模型平台,零编码集成嵌入第三方系统,42K+星标见证专属智能方案
  • 【Hot100】LeetCode—283. 移动零
  • [Spring] Spring AOP
  • 修复本地终端(windows)连接服务器使用zsh出现乱跳的问题
  • 有道云docx转换markdown,导入hugo发布到github page,多平台发布适配
  • 【Unity】案例 —— 胡闹厨房联机案例(持续更新)
  • css写一个按钮流光动画效果
  • Kubernetes-ingress
  • linux主机间免密登录
  • javascript 总结(常用工具类的封装)
  • JavaScript标准库系列——Math对象和Date对象(二)
  • JavaScript工作原理(五):深入了解WebSockets,HTTP/2和SSE,以及如何选择
  • js递归,无限分级树形折叠菜单
  • MySQL几个简单SQL的优化
  • PHP的Ev教程三(Periodic watcher)
  • Vue.js 移动端适配之 vw 解决方案
  • 技术发展面试
  • 理解 C# 泛型接口中的协变与逆变(抗变)
  • 排序(1):冒泡排序
  • 让你的分享飞起来——极光推出社会化分享组件
  • 少走弯路,给Java 1~5 年程序员的建议
  • 使用common-codec进行md5加密
  • 云大使推广中的常见热门问题
  • 阿里云服务器如何修改远程端口?
  • #NOIP 2014#day.2 T1 无限网络发射器选址
  • (09)Hive——CTE 公共表达式
  • (1)Nginx简介和安装教程
  • (30)数组元素和与数字和的绝对差
  • (4)STL算法之比较
  • (Charles)如何抓取手机http的报文
  • (C语言)字符分类函数
  • (JS基础)String 类型
  • (Mac上)使用Python进行matplotlib 画图时,中文显示不出来
  • (笔记)M1使用hombrew安装qemu
  • (黑马出品_高级篇_01)SpringCloud+RabbitMQ+Docker+Redis+搜索+分布式
  • (转)Scala的“=”符号简介
  • (转)四层和七层负载均衡的区别
  • ***利用Ms05002溢出找“肉鸡
  • ./mysql.server: 没有那个文件或目录_Linux下安装MySQL出现“ls: /var/lib/mysql/*.pid: 没有那个文件或目录”...
  • .cn根服务器被攻击之后
  • .Net Core和.Net Standard直观理解
  • .net framwork4.6操作MySQL报错Character set ‘utf8mb3‘ is not supported 解决方法
  • .NET Micro Framework初体验
  • .Net Redis的秒杀Dome和异步执行
  • .net解析传过来的xml_DOM4J解析XML文件
  • .net企业级架构实战之7——Spring.net整合Asp.net mvc
  • .net中我喜欢的两种验证码
  • @PreAuthorize注解
  • @SpringBootApplication 注解