vue-axios-optimize
v2.1.1
Published
vue项目对axios请求的优化,实现可配置展示全局加载动画,可配置是否重复请求时取消前面的请求或者阻止后面的请求,已经控制请求并发数量,接口缓存
Downloads
17
Readme
vue-axios-optimize使用说明
vue-axios-optimize是一个对axios请求优化的vue插件包,引入此包之后,并进行相关配置,即可轻松实现全局请求加载动画,重复请求时取消前面的请求或者阻止后面的请求,并且可实现请求并发数量控制以及接口缓存。 可阅读此文章 了解
安装
npm install vue-axios-optimize -S
axios版本
axios版本建议大于0.27.2 , 作者测试版本为 "^0.27.2"、"^1.3.4"
引入
在src/api目录下新建axios-optimize.js文件
api目录大致如下
src
api
modules
common-api.js
index.js
axios.js
axios-optimize.js
axios-optimize.js文件内容大致如下
import axios from "axios"
import instance from "@/api/axios"
import axiosOptimize from "vue-axios-optimize"
import store from "@/store"
import {MessageBox} from "element-ui"
const AxiosOptimize = new axiosOptimize(axios, instance, {
maxReqNum: 2, // 同时最多请求数量 选配 默认 4
cacheNum: 2, // 缓存数量 选配 默认10
responseTypesStr: "arraybuffer,blob", // 当axios请求设置 responseType为arraybuffer或blob时,直接返回原始数据 选配
showLoadingFun: (config, requestingNum) => { // 当需要加载动画的请求数量不为0时的回调函数
store.commit("app/SET_LOADING_STATUS", true)
},
hideLoadingFun: (config, requestingNum) => { // 当需要加载动画的请求数量为0时的回调函数
store.commit("app/SET_LOADING_STATUS", false)
},
responseResultFun: (res) => { // 响应数据格式化
return res.data
},
openRefresh: true, // 是否开启无感知刷新token 以下配置均与无感知刷新token有关 如无需配置无感知刷新token 可忽略
code: "code", // 判断响应码的字段标识 默认code
accessToken: "accessToken", // headers存放accessToken的字段名 默认 accessToken 用于判断当前接口是否使用的最新的token
accessTokenExpirationCode: 401, // accessToken过期时 接口响应状态码 默认 数字类型 401
refreshTokenExpirationCode: 403, // 刷新token接口请求报错时的 响应状态码 默认 数字类型 403
setAccessTokenFun: (config, accessToken) => { // 设置接口请求token的 并返回新的config 默认为 config.headers.Authorization = "Bearer " + accessToken
config.headers.Authorization = "Bearer " + accessToken
return config
},
getRefreshTokenFun: () => { // 获取refreshToken的方法
return store.getters.refreshToken
},
getAccessTokenFun: () => { // 获取accessToken的方法
return store.getters.accessToken
},
refreshTokenStore: (refreshToken) => { // 调用刷新token的方法 并将获取到的数据存储到cookie 且需要将接口返回的数据 resolve(data)
return store.dispatch("user/refreshToken", refreshToken)
},
reloginFun: async(response) => { // 刷新token接口也报错后的处理逻辑 建议进行类似如下方法处理
// 重新登录方法 弹框提示 点击确认后 建议清除 缓存中token等信息后 刷新页面
MessageBox.alert(`${response.message}`, "提示", {
confirmButtonText: "OK",
showClose: false,
callback: async(action) => {
if (action === "confirm") {
// 清除缓存中的token等信息
store.commit("user/CLEAR_AUTH")
// 刷新浏览器是为了 跳转登录页时query的redirect 会带上 当前页面地址(路由拦截处的逻辑)
window.location.reload()
}
}
})
}
})
export default AxiosOptimize
axios.js的内容需要做些细微的更改 大致内容如下
import axios from "axios"
import Message from "@/plugins/reset-message.js"
import store from "@/store"
// 创建axios实例
const service = axios.create({
baseURL: XXX,
timeout: XXX // 请求超时时间
})
// request拦截器
service.interceptors.request.use(
config => {
const accessToken = store.getters.accessToken
if (accessToken) {
// 配置无感知刷新token时 建议请求头多加个 accessToken, 如为其他字段可 配置 为其他字段 用于判断当前接口携带的accessToken
config.headers.accessToken = accessToken
// 用于做接口权限标识
config.headers.Authorization = "Bearer " + accessToken
}
return config
},
error => {
// 需要return
return Promise.reject(error)
}
)
// respone拦截器
service.interceptors.response.use(
async response => {
const {data, config, status, request} = response
// 如果自定义代码不是200,则判断为错误。
if (status !== 200) {
Message({
message: data.message || "Error",
type: "error",
duration: 5 * 1000
})
// 错误响应时,多返回一个config 和 responseErr设置为true 让vue-axios-optimize 拿到config 以及知道 这是一个错误的响应数据
return { ...data, config, responseErr: true}
} else {
// 二进制数据则直接返回
if (request.responseType === "blob" || request.responseType === "arraybuffer"){
// 直接返回数据
return response
}
if (data.code === 200) {
// 正常响应时,多返回一个config 让vue-axios-optimize 拿到config
return { ...data, config}
}
if (data.code === 401 || data.code === 403) {
// 错误响应时,多返回一个config 和 responseErr设置为true 让vue-axios-optimize 拿到config 以及知道 这是一个错误的响应数据
return { ...data, config, responseErr: true}
}
Message({
message: data.message || "Error",
type: "error",
duration: 5 * 1000
})
// 错误响应时,多返回一个config 和 responseErr设置为true 让vue-axios-optimize 拿到config 以及知道 这是一个错误的响应数据
return { ...data, config, responseErr: true}
}
},
error => {
// 取消请求时 不报错误信息
if (error.name !== "CanceledError") {
Message.error(error.message)
}
// 需要return
return Promise.reject(error)
}
)
export default service
接口处使用,如commo-api.js 大致如下
import axiosRequest from "@/api/axios-optimize"
// 需要配置 请求接口时 不加载全局动画 则 配置 noShowLoading: true
// 需要配置 缓存的接口 则 配置 cache: true 否则 配置为 false 或 不配置
// 需要配置 重复请求时 取消前面的请求 则 配置 preventDuplicateRequestsType: "cancel"
// 需要配置 重复请求时 禁用后面的请求 则 配置 preventDuplicateRequestsType: "prevent"
// 需要配置 返回数据是否添加 IS_COMPLETE 是否完成字段 则 配置 showIsComplete: true
// 需要配置 当同时请求很多接口,且还有很多接口在队列时,有接口报错,是否终止所有队列中的接口请求 removeRemainingTasksWhenError: true
// 需要配置 全路经(包括入参数据)为接口唯一标识的 则配置 fullPath: true 否则 配置为 false 或 不配置 否则仅仅以URL为唯一标识
// 当需要配置无感知刷新token时,对于刷新token接口需要配置 isRefreshToken 为true 否则配置为 false 或者不 配置
// get 请求demo
export function getDemo(
data = {},
config = {
noShowLoading: true, // 配置不展示加载动画
preventDuplicateRequestsType: "cancel" // 配置重复请求时 取消前面的请求
}
) {
return axiosRequest.get(`/xiaobu-admin/getDemo`, { params: data, ...config })
}
// post 请求demo
export function postDemo(data = {}, config = {}) {
return axiosRequest.post(`/xiaobu-admin/postDemo`, data, config)
}
// delete 请求demo1 使用data作为参数 参数不展示在 请求路径上
export function deleteDemo1(data = {}, config = {}) {
return axiosRequest.delete(`/xiaobu-admin/deleteDemo1`, { data, ...config })
}
// delete 请求demo2 使用params作为参数 参数展示在 请求路径上
export function deleteDemo2(data = {}, config = {}) {
return axiosRequest.delete(`/xiaobu-admin/deleteDemo2`, {
params: data,
...config
})
}
// put 请求demo
export function putDemo(data = {}, config = {}) {
return axiosRequest.put(`/xiaobu-admin/putDemo`, data, config)
}
// patch 请求demo
export function patchDemo(data = {}, config = {}) {
return axiosRequest.patch(`/xiaobu-admin/patchDemo`, data, config)
}
new axiosOptimize(axios, instance, options)参数说明
| 参数 | 说明 | 来源 | | -------- | ------------------------- | ------------------------------------- | | axios | 安装axios中的axios | import axios from 'axios' | | instance | 创建好的axios实例,已经配置好请求头等相关内容 | import instance from '@/api/axios.js' | | options | 一些配置,详情继续阅读文档 | 自定义配置 |
options配置
| 参数 | 类型 | 说明 | 是否必传 | 默认值 | | ------------------------------------------------------------ | -------- | ------------------------------------------------------------ | ------------------------- | ------------------------------------------------------------ | | maxReqNum | Number | 同时最大可请求数量,高并发任务时,可同时进行的任务处理数量 | 否 | 4 | | cacheNum | Number | 可缓存的键值对个数 | 否 | 10 | | showLoadingFun(config, requestingNum) | Function | 展示动画,config为该请求的config,requestingNum为目前正在请求几个接口,此处可执行一些展示全局动画的操作 | 否 | 无 | | hideLoadingFun(config, requestingNum) | Function | 隐藏动画,config为该请求的config,requestingNum为目前正在请求几个接口,此时应该为0,此处可执行关闭全局动画的操作 | 否 | 无 | | openRefresh | Boolean | 是否开启无感知刷新token | 否 | false | | refreshApiUrl | String | 请求刷新token接口的api地址 如/xiaobu-admin/refresh-token | 当openRefresh为true时必传 | 无 | | getRefreshTokenFun() | Function | 获取当前项目的 refreshToken方法, 记得 return 回去 | 当openRefresh为true时必传 | 无 | | getAccessTokenFun() | Function | 获取当前项目的 accessToken方法, 记得 return 回去 | 当openRefresh为true时必传 | 无 | | reloginFun(response) | Function | response 为axios实例中返回的数据,此处建议执行清除token相关缓存并弹框提示,点击确认进行刷新页面操作 | 当openRefresh为true时必传 | 无 | | refreshTokenStore(refreshToken) | Function | refreshToken为当前浏览器缓存的refreshToken,需要返回一个Promise,利用此refreshToken调用接口获取新的accessToken 并设置。v1.0.6及以上无需返回任何数据 | 当openRefresh为true时必传 | 无 | | setAccessTokenFun(config, accessToken) (v1.0.8已废除, V2.0.2 弄回来 并添加默认值) | Function | config为该请求的config,accessToken 为新获取的accessToken, 此处需要将accessToken设置到请求头中 | 当openRefresh为true时必传 | setAccessTokenFun: (config, accessToken) => { // 设置接口请求token的 并返回新的config 默认为 config.headers.Authorization = "Bearer " + accessToken config.headers.Authorization = "Bearer " + accessToken return config }, | | responseResultFun(res) | Function | res为axios实例返回的res,格式化接口请求成功后返回的数据 | 非必传 | axios实例返回的res | | formatAccessTokenFun(data) v1.0.6已废除 | Function | data为responseResultFun报错时返回的res | 非必传 | axios实例返回的res.data.accessToken | | accessTokenExpirationCode | number | 配置accessToken过期返回的业务状态码 | 非必传 | 401 | | refreshTokenExpirationCode | number | 配置refreshToken过期返回的业务状态码 | 非必传 | 403 | | responseTypesStr(v1.0.2) | String | 配置数据返回类型,实现当此类型时返回原封不动的响应数据的data数据 | 非必传 | 无 | | timeout(V2.1.0) | Number | 配置缓存数据时,伪加载动画的请求时间。获取缓存数据时会执行showLoadingFun,timeout毫秒后会执行hideLoadingFun。 | 非必传 | 300 |
store/modules/user.js代码大致如下
import { setCookie, getCookie, removeCookie, accessTokenKey, refreshTokenKey } from "@/utils/cookie"
import { commonApi } from "@/api"
const getDefaultState = () => {
return {
accessToken: getCookie(accessTokenKey) || "", // 认证token
refreshToken: getCookie(refreshTokenKey) || "", // 刷新token
}
}
const state = getDefaultState()
const mutations = {
// 重置初始化值
RESET_STATE: (state) => {
Object.assign(state, getDefaultState())
},
// 设置token
SET_TOKEN: (state, data) => {
const { accessToken, refreshToken, expiresIn} = data
state.accessToken = accessToken
setCookie(accessTokenKey, accessToken, expiresIn)
state.refreshToken = refreshToken
setCookie(refreshTokenKey, refreshToken, expiresIn)
},
// 清除token 及其他可能影响操作的缓存数据
CLEAR_AUTH: (state) => {
state.accessToken = ""
removeCookie(accessTokenKey)
state.refreshToken = ""
removeCookie(refreshTokenKey)
// ...
}
}
const actions = {
// 设置项目token
setToken({commit}, data) {
return new Promise((resolve, reject) => {
commit("SET_TOKEN", data)
resolve()
})
},
// 刷新token
refreshToken({commit}, refreshToken) {
return new Promise((resolve, reject) => {
commonApi.refreshToken({refreshToken}).then(data => {
commit("SET_TOKEN", data)
resolve()
})
})
},
}
export default {
namespaced: true,
state,
mutations,
actions
}
注意
如果要配置无感知刷新token时,对后端是有要求的,需要做到当accessToken过期refreshToken未过期时,请求接口的业务状态码 code为 配置的 accessTokenExpirationCode 的值, 默认401,当refreshToken过期或其他问题报错导致系统无法运行的错误时 业务状态码code 应为配置的 refreshTokenExpirationCode, 默认403
当部分页面接口请求在catch处有操作时 需添加语句, 参考如下示例
this.loading = true
testApi.getUserList(this.addDateRange(this.queryParams, this.dateRange)).then(res => {
const response = res.data
this.list = response.rows
this.total = response.total
this.loading = false
}).catch(err => {
// 此处需要添加 如果是取消请求 或者是 阻止请求时 不进行操作
if (err.name === "CanceledError") {
return
}
this.loading = false
})
特别注意
vue2项目的vue.config.js 需要添加如下配置,对插件包进行编译。
module.exports = {
...
transpileDependencies: [
"vue-axios-optimize"
],
...
}
总结
如有疑问,可关注微信公众号【爆米花小布】进行咨询。
打赏
微信公众号【爆米花小布】,抖音号【爆米花小布】 更多好玩的插件 vue2-element-dict字典包插件使用文档
更新日志
2.1.1
- 【fix】修复get请求和delete请求配置fullPath参数为 true时,会报错的bug
2.1.0
- 【优化】新增timeout配置,实现缓存数据时的伪加载时间,从缓存中获取数据时会触发 showLoadingFun, timeout毫秒后会执行hideLoadingFun
2.0.9
- 【修复】修复请求链接相同时,请求方式不同也会被当做同个请求的问题。
2.0.8
- 【优化】新增showIsComplete参数,实现只有配置了才在请求返回数据中添加 IS_COMPLETE 是否请求完成字段。
2.0.6
- 【优化】新增removeRemainingTasksWhenError参数,实现当某个请求报错时,尽可能的阻止剩余未发起的请求。
2.0.5
- 【修复】接口报错时,原封不动reject返回原始数据
2.0.3
- 【修复】修复缓存接口时,取消重复请求,页面逻辑代码的catch不执行的问题
2.0.2
- 【功能】阻止重复请求的代码逻辑变更
- 【功能】无感知刷新token的代码逻辑变更
- 【修复】配置高并发请求数量后,取消请求存在取消不了的情况
- 【优化】配置接口缓存后,新增可删除接口缓存的功能
- 【注意】options配置变化,及接口捕获异常处的逻辑判断
2.0.1
- 【功能】实现接口缓存配置 options新增配置 cacheNum 配置最大缓存数量, 接口配置处可配置 cache: true。
注意:如下几种情况不建议配置缓存
- 表单提交的接口
- 数据频繁更新的接口
- 删除数据接口
2.0.0
- 【功能】实现并发请求数量控制,options新增maxReqNum参数配置 默认值为 4 ,表示同时可请求4个接口,剩余的接口陆续排队
- 【优化】当接口返回数据格式为对象格式时,会多添加一个 IS_COMPLETE 表示当前全部请求任务是否已完成
- 【调整】2.0.0版本 axios-optimize.js 文件不暴露 instance实例,且接口调用方法仅 支持 .get .post .delete .patch .put 形式调用, 具体查看文档示例
1.0.8
- 【优化】废除options的setAccessTokenFun配置项
- 【优化】将返回数据的config去除
1.0.6
- 【优化】废除options的formatAccessTokenFun配置项
- 【优化】refreshTokenStore由原来的resolve接口返回的数据,改为resolve(accessToken)
1.0.5
- 【优化】修复部分检查代码比较严格的时候 会报 responseType 未定义的错误的问题
1.0.3
- 【优化】修复部分检查代码比较严格的时候 会报 noShowLoading 未定义的错误的问题
1.0.2
- options新增responseTypesStr配置项,字符串类型,多个时使用英文逗号隔开,此返回类型的数据直接返回原有数据的data数据。在axios.js原封装函数中返回原始的响应返回数据。解决文件类型数据时不可用的问题
1.0.1
- 修复单词错误问题 isPervent 修改为 isPrevent
1.0.0
- 初始版本