vue3基于axios配置请求拦截器响应拦截器以及无感刷新token的实现

vue3基于axios配置请求拦截器响应拦截器以及无感刷新token的实现

  • 一、下载并引入 axios
  • 二、引入 element-plus 消息提示
  • 三、配置基础地址
  • 四、创建 axios 实例
  • 五、配置请求拦截器
  • 六、定义是否刷新 token 的变量以及存储请求队列的数组
  • 七、配置响应拦截器以及实现无感刷新 token
  • 八、导出axios
  • 九、封装接口请求
  • 十、使用接口请求
  • 十一、完整代码

一、下载并引入 axios

npm i axios
  • 创建request=>index.js
import axios from 'axios'

二、引入 element-plus 消息提示

import { ElMessage, ElMessageBox } from 'element-plus'

三、配置基础地址

可参考历史文章vue3项目打包上线后,如何配置api接口地址,省去更换api再次打包

//生产环境下读取 public=>static=>config.js 中的 api 变量(用于上线后动态配置接口地址)
const BASE_URL =
process.env.NODE_ENV === 'development'
? process.env.VUE_APP_API_URL
: window.webConfig.webApiBaseUrl

四、创建 axios 实例

const request = axios.create({
baseURL: BASE_URL,
timeout: 30000,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
})

五、配置请求拦截器

request.interceptors.request.use((config) => {
config.headers = config.headers || {}, //设置请求头
config.headers['Token'] = localStorage.getItem('Token') || ''
config.headers['Code'] = localStorage.getItem('Code') || ''
return config
})

六、定义是否刷新 token 的变量以及存储请求队列的数组

//是否刷新 token
let isRefreshing = false
//请求队列
let requestList = [] as any[]

七、配置响应拦截器以及实现无感刷新 token

request.interceptors.response.use(
async (res: any) => {
// 路由
const Code: number = res.data.Code || 0const config = res.config//处理token过期==>更新tokenif (Code == -1) {if (!isRefreshing) {isRefreshing = true//id (用于获取token)const appid = process.env.VUE_APP_APPID.replace(/"/g, '')//密钥 (用于获取token)const secret = process.env.VUE_APP_SECRET.replace(/"/g, '')//请求获取token接口return (request({url: `outside/getAccessToken?appid=${appid}&secret=${secret}`,method: 'GET',}).then((res) => {//存token缓存localStorage.setItem('Token', res.data.data)config.headers.token = res.data.datalet response = request(config)// 刷新成功后将请求队列里的请求依次执行requestList.forEach((cb) => cb())requestList = [] // 执行完毕后将请求队列置空return response}).finally(() => {isRefreshing = false}))} else {return new Promise((resolve) => {requestList.push(() => {config.headers.token = localStorage.getItem('Token')let response = request(config)resolve(response)})})}} else if (Code == 0) {//处理code过期==>退出登录 (tokenExpired是防止code过期后,下方提示消息显示多次)let tokenExpired = localStorage.getItem('tokenExpired')if (tokenExpired == 'false' || !tokenExpired) {localStorage.setItem('tokenExpired', 'true')ElMessageBox.confirm('登录已过期,请重新登录!', '提示', {confirmButtonText: '确定',showClose: false,showCancelButton: false,closeOnClickModal: false,type: 'warning',}).then(() => {//清除缓存localStorage.removeItem('Token')localStorage.removeItem('UserGlobalStore')localStorage.removeItem('Code')// 重新加载页面(清除路由缓存)window.location.reload()// 在页面加载完成后跳转到登录页面window.onload = function () {window.location.href = '/login'}})} else {//清除缓存localStorage.removeItem('Token')localStorage.removeItem('UserGlobalStore')localStorage.removeItem('Code')// 重新加载页面(清除路由缓存)window.location.reload()// 在页面加载完成后跳转到登录页面window.onload = function () {window.location.href = '/login'}}}  else {return Promise.resolve(res)}},
(err) => {
//接口出错
ElMessage.error(err.message)
return Promise.reject(err)
}
)

八、导出axios

export default request

九、封装接口请求

import request from '@/request/index'export function getYourApi(data: Object) {
return request({
url: 'yourApi',
method: 'GET',
params: data,
})
}

十、使用接口请求

import { getYourApi } from '@/api/yourApi'
getYourApi({}).then((res) => {
...
}).catch((err) => {
})

十一、完整代码

  • 第一步到第八步代码
import axios from 'axios'
import { ElMessage, ElMessageBox } from 'element-plus'//生产环境下读取 public=>static=>config.js 中的 api 变量(用于上线后动态配置接口地址)
const BASE_URL =
process.env.NODE_ENV === 'development'
? process.env.VUE_APP_API_URL
: window.webConfig.webApiBaseUrlconst request = axios.create({
baseURL: BASE_URL,
timeout: 30000,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
})request.interceptors.request.use((config) => {
config.headers = config.headers || {}, //设置请求头
config.headers['Token'] = localStorage.getItem('Token') || ''
config.headers['Code'] = localStorage.getItem('Code') || ''
return config
})//是否刷新 token
let isRefreshing = false
//请求队列
let requestList = [] as any[]request.interceptors.response.use(
async (res: any) => {
// 路由
const Code: number = res.data.Code || 0const config = res.config//处理token过期==>更新tokenif (Code == -1) {if (!isRefreshing) {isRefreshing = true//id (用于获取token)const appid = process.env.VUE_APP_APPID.replace(/"/g, '')//密钥 (用于获取token)const secret = process.env.VUE_APP_SECRET.replace(/"/g, '')//请求获取token接口return (request({url: `outside/getAccessToken?appid=${appid}&secret=${secret}`,method: 'GET',}).then((res) => {//存token缓存localStorage.setItem('Token', res.data.data)config.headers.token = res.data.datalet response = request(config)// 刷新成功后将请求队列里的请求依次执行requestList.forEach((cb) => cb())requestList = [] // 执行完毕后将请求队列置空return response}).finally(() => {isRefreshing = false}))} else {return new Promise((resolve) => {requestList.push(() => {config.headers.token = localStorage.getItem('Token')let response = request(config)resolve(response)})})}} else if (Code == 0) {//处理code过期==>退出登录 (tokenExpired是防止code过期后,下方提示消息显示多次)let tokenExpired = localStorage.getItem('tokenExpired')if (tokenExpired == 'false' || !tokenExpired) {localStorage.setItem('tokenExpired', 'true')ElMessageBox.confirm('登录已过期,请重新登录!', '提示', {confirmButtonText: '确定',showClose: false,showCancelButton: false,closeOnClickModal: false,type: 'warning',}).then(() => {//清除缓存localStorage.removeItem('Token')localStorage.removeItem('UserGlobalStore')localStorage.removeItem('Code')// 重新加载页面(清除路由缓存)window.location.reload()// 在页面加载完成后跳转到登录页面window.onload = function () {window.location.href = '/login'}})} else {//清除缓存localStorage.removeItem('Token')localStorage.removeItem('UserGlobalStore')localStorage.removeItem('Code')// 重新加载页面(清除路由缓存)window.location.reload()// 在页面加载完成后跳转到登录页面window.onload = function () {window.location.href = '/login'}}}  else {return Promise.resolve(res)}},
(err) => {
//接口出错
ElMessage.error(err.message)
return Promise.reject(err)
}
)export default request

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/34364.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux CentoS安装RabbitMQ:一键安装指南

有两种安装方法,官方推荐使用 docker安装RabbitMQ 一、Docker安装RabbitMQ 1、安装docker 参考我之前的文章:Centos7.5搭建docker并且部署Lnmp环境(小白入门docoker)_centos7.5安装docker和docker-compose-CSDN博客 2、安装Ra…

【实用软件】Paragon NTFS for Mac 15下载及安装教程

​习惯上来说所有操作只需轻轻一点:轻量级的快捷菜单栏,可访问所有NTFS驱动器并执行最常见的卷操作,如挂载,卸载和验证,从菜单栏中快速启动NTFS for Mac界面,一键点击,更加方便。11510182322410…

Scope XY Project的使用

1.Scope XY Project的功能介绍与使用方法 添加监控变量 绘制成一个三角形 XY进行对调操作 修改XY轴的比例修改显示输出 2.Cursor的使用方法 游标线的添加测量 3.Reporting功能的使用方法 到处对应的报表数据 添加对应的报告数据

一、Jquery入门(超详)

* [5.3 jQuery 对象和 DOM 对象之间的相互转换](about:blank#53_jQuery__DOM__271)* * [5.3.1 jQuery 对象转换为 DOM 对象](about:blank#531_jQuery__DOM__282)* [5.3.2 DOM 对象转换为 jQuery 对象](about:blank#532_DOM__jQuery__295)六、 解决 jQuery 和其他库的冲…

vue3 中v-model语法糖(2024-06-21)

一、 vue2 中 v-model 语法糖 实现父子组件双向数据绑定&#xff0c;一个输入框或者组件指定绑定一个 v-model 1. 父组件写法 <template><div><h1>App</h1><h2>{{ count }}</h2><input type"text" v-model"count&quo…

Apache Calcite - 使用框架Sql解析器解析Sql

前言 Calcite提供了org.apache.calcite.sql.parser.SqlParser来解析sql&#xff0c;通过访问者模式&#xff0c;在解析过程中访问Sql中的不同元素&#xff0c;最终完成特定的功能。 使用举例 使用Calcite解析SQL主要涉及以下几个步骤&#xff1a; 创建SqlParser对象&#xf…

Linux:基础IO(三.软硬链接、动态库和静态库、动精态库的制作和加载)

上次介绍了基础IO&#xff08;二&#xff09;&#xff1a;Linux&#xff1a;基础IO&#xff08;二.缓冲区、模拟一下缓冲区、详细讲解文件系统&#xff09; 文章目录 1.软硬链接1.1硬链接1.2软链接使用场景 2.动态库和静态库1.1回顾1.2静态库的制作和使用为什么要有库制作者角度…

重学java 85.Java反射、注解、枚举总结

凡事往好处想&#xff0c;人生便会豁达 —— 24.6.24 一、Junit单元测试 1.概述: Junit是一个单元测试框架,可以代替main方法去执行其他的方法 2.使用 a.导入jar包 b.注解 Test —— 单独执行一个方法 Before —— 在Test之前执行.有多少个Test执行.Before对应的方法就执行多少…

常见排序算法及其C语言实现

排序算法在计算机科学中是一个非常重要的主题。本文将详细介绍几种常见的排序算法&#xff0c;包括快速排序、归并排序、堆排序、冒泡排序、选择排序、插入排序、桶排序和二分查找插入排序&#xff0c;并提供每种算法的C语言实现代码。 1. 快速排序&#xff08;Quick Sort&…

毫米波移动通信系统中的波束赋形—模数混合的波束赋形架构

模数混合的波束赋形将波束赋形分为了模拟波束赋形与数字波束赋形两部分&#xff0c;其模拟部分通过移相器实现&#xff0c;数字部分通过基带预编码实现&#xff0c;&#xff0c;其结构如图2所示。当射频链路数目NRF为1时&#xff0c;认为其是一种特殊的模数混合的波束赋形。 此…

【计算机视觉】人脸算法之图像处理基础知识【七】

直方图均衡化 直方图均衡化是一种常用的图像处理技术&#xff0c;用于改善图像的对比度&#xff0c;特别是在图像的细节被埋没在暗部或亮部区域时。通过重新分配图像的像素强度值&#xff0c;使得图像的整体对比度增强&#xff0c;从而让更多的细节变得可见。 import cv2 imp…

最小生成树模板(prim,heap-prim,kruskal)

prim 出圈法&#xff0c;时间复杂度 O ( n 2 ) O(n^2) O(n2) #include<iostream> #include<vector> using namespace std; #define MAX_N 5000 #define inf 100000000 struct edge{int v,w; }; vector<edge>e[MAX_N5]; int d[MAX_N5],vis[MAX_N5]; int n,m…

IO-Iink事件

IO-LINK事件功能 IO-Link的事件功能是其通信协议中的一项重要特性&#xff0c;主要用于传输设备的故障信息和维护信息。IO-Link支持三种数据类型&#xff1a;过程数据、参数数据和事件数据。其中&#xff0c;事件数据就是用于此目的。 当IO-Link设备&#xff08;如传感器或执…

NepnepxCATCTF Pwn-Chao

文章目录 参考类型混淆异常处理的栈回退机制虚表和类的恢复假想的程序结构逆向工程场景步骤解析 idabug检查找虚表strupsc_str()alloca异常逆向maindisplayupdatecreate 新东西exp和思路 参考 https://www.cnblogs.com/winmt/articles/17018284.html 类型混淆 关于C中由虚函…

Java中如何解决BadPaddingException异常?

Java中如何解决BadPaddingException异常&#xff1f; 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01; 在Java编程中&#xff0c;BadPaddingException异常是一个…

HarmonyOS Next开发学习手册——应用启动框架AppStartup

概述 AppStartup提供了一种简单高效的初始化组件的方式&#xff0c;开发者可以使用AppStartup来显示的设置组件的初始化顺序以及之间的依赖关系&#xff0c;支持异步初始化组件加速应用的启动时间。开发者需要分别为待初始化的组件实现AppStartup提供的 StartupTask 接口&…

DoubleSummaryStatistics 及其相关类之-简介

1. DoubleSummaryStatistics 使用简介 在Java 8中&#xff0c;DoubleSummaryStatistics 类被引入作为 java.util 包的一部分。它是一个用于收集统计数据&#xff08;如计数、最小值、最大值、和、平均值等&#xff09;的类&#xff0c;特别适用于处理 double 类型的数据。 Do…

【OpenGauss源码学习 —— (ALTER TABLE(修改表空间))】

ALTER TABLE&#xff08;列存删除列&#xff09; ALTER TABLE ... SET TABLESPACEExecChangeTableSpaceForRowTable 函数ATExecSetTableSpace 函数 ExecChangeTableSpaceForRowPartition 函数ATExecSetTableSpaceForPartitionP3 函数 ExecChangeTableSpaceForCStoreTable 函数C…

DeepSeek-Coder-v2击败GPT-4 Turbo,成为竞技场最强开源编码模型!

目录 01 编码与数学击败GPT-4 Turbo 02 深度求索&#xff1a;价格战的导火索 就在刚刚&#xff0c;竞技场排名再次刷新&#xff1a;深度求索的DeepSeek-Coder-v2成为竞技场最强开源编码模型&#xff01; 它在Coding Arena中已攀升至第4名&#xff0c;水平接近GPT-4 Turbo。 没…

mysql的information_schema浅析

information_schema 是 MySQL 中的一个虚拟数据库&#xff0c;它包含了关于 MySQL 服务器的所有元数据。 information_schema 作用 元数据管理&#xff1a;提供关于数据库、表、列、索引、权限等的信息。 性能优化&#xff1a;帮助了解数据库结构和索引使用情况&#xff0c;便…