关于 vue3 axios的封装,并发请求相关
简介
Axios 是一个基于 promise 网络请求库,作用于node.js 和浏览器中。 它是 isomorphic 的(即同一套代码可以运行在浏览器和node.js中)。在服务端它使用原生 node.js http 模块, 而在客户端 (浏览端) 则使用 XMLHttpRequests。
请求方法别名
为了方便起见,axios为所有支持的请求方法提供了别名(配置项在这里就不多做介绍,官网都有axios):
axios(config)
axios.request(config)
axios.get(url [,config])
axios.post(url [,data [,config]])
axios.put(url [,data [,config]])
axios.delete(url [,config])
axios.patch(url [,data [,config]])
axios.head(url [,config])
封装之前,需要下载axios依赖,这些准备工作做好后才能进行以下操作。
一,首先创建utils目录,在该目录下创建index.ts 文件,我这里用的是ts封装。
// 引入axios插件
import axios, { AxiosError, AxiosRequestConfig, AxiosResponse } from 'axios'
// import { ElMessage } from 'element-plus'
// 使用create 创建axios示例 (当然这里存在很多配置选项,具体需要具体配置)
const instance = axios.create()
// 我在这里直接指定了post请求的 请求类型 Content-Type, 可不设置看需要
instance.defaults.headers.post['Content-Type'] = 'application/json; charset=UTF-8'
// 声明一个数组用于存储每个ajax请求的取消函数和ajax标识
const pending: any = []
const { CancelToken } = axios // axios 内置方法,此方法是为取消请求
// 入参removeAll 为true时,清空数组。
const removePending = (ever: AxiosRequestConfig, removeAll?: boolean) => {
for (let i = 0; i < pending.length; i += 1) {
if (removeAll) {
pending[i].f() // 执行取消操作
pending.splice(i, 1) // 把这条记录从数组中移除
} else if (
pending[i].u === `${ever.url!.replace(/d=\d+/, '')}&${ever.method}`
) {
// 当当前请求在数组中存在时执行函数体
pending[i].f() // 执行取消操作
pending.splice(i, 1) // 把这条记录从数组中移除
}
}
}
const removeOtherPending = (ever: string, removeAll?: boolean) => {
for (let i = 0; i < pending.length; i += 1) {
if (pending[i].u.indexOf(ever) !== -1) {
// 当当前请求在数组中存在时执行函数体
pending[i].f() // 执行取消操作
pending.splice(i, 1) // 把这条记录从数组中移除
}
}
}
// http request 拦截器
instance.interceptors.request.use(
(config: AxiosRequestConfig) => {
// canMoreActive 参数用来判断是否需要被添加到pending队列中 该参数是设置在请求头中的,需要后台进行配置该参数
if (!config.headers!.canMoreActive) {
// 该接口是否可以多并发
removePending(config) // 在一个ajax发送前执行一下取消操作
// eslint-disable-next-line no-param-reassign
config.cancelToken = new CancelToken((c) => {
// 这里的ajax标识我是用请求地址&请求方式拼接的字符串,当然你可以选择其他的一些方式
pending.push({
// 去除添加的日期导致的链接不一致
u: `${config.url!.replace(/d=\d+/, '')}&${config.method}`,
f: c,
})
})
}
return config
},
(error: AxiosError) => Promise.reject(error)
)
// 必须在项目中重写该方法,因为如果调用多次use方法,是一个队列,函数都会执行
/* instance.interceptors.response.use(
(response: AxiosResponse) => {
removePending(response.config) // 在一个ajax响应后再执行一下取消操作,把已经完成的请求从pending中移除
if (response.data.code === 700) {
ElMessage({
type: 'error',
message: response.data.msg,
})
}
return response
},
(error: AxiosError) => Promise.reject(error)
) */
/**
* 封装get方法
* @param url 请求url
* @param params 参数
* @param config config参数
* @returns {Promise}
*/
function fetch(
url: string,
params: any = {},
config = {
headers: {},
}
): Promise<any> {
return new Promise((resolve, reject) => {
// 参数增加一个随机数解决浏览器缓存问题
instance.get(`${url}?d=${new Date().getTime()}`, {
params,
headers: config.headers, // 设置get请求头,用来传递canMoreActive参数
}).then((response) => {
if (response) {
resolve(response.data)
}
}).catch((err) => {
reject(err)
})
})
}
/**
* 封装post请求
* @param url 请求url
* @param data 参数
* @param config config参数
* @returns {Promise}
*/
function post(
url: string,
params: any = {},
config = {},
ContentType = ''
): Promise<any> {
return new Promise((resolve, reject) => {
if (ContentType) {
instance.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8'
} else {
instance.defaults.headers.post['Content-Type'] = 'application/json; charset=UTF-8'
}
instance.post(url, params, config).then((response) => {
if (response) {
resolve(response.data)
}
}).catch((err) => {
reject(err)
})
})
}
/**
* 封装 DELETE 请求
* @param {string} url 请求的URL
* @param {object} data 请求参数
* @param {object} config 额外的 Axios 请求配置
* @returns {Promise<any>}
*/
function del(
url: string,
data: any = {},
config: AxiosRequestConfig = {}
): Promise<any> {
return new Promise((resolve, reject) => {
// 发起 DELETE 请求
// 使用 delete 方法,注意要传递参数在 data 属性中
instance.delete(url, {...config, data}).then((response: AxiosResponse) => {
resolve(response.data) // 解析响应数据
}).catch((error: AxiosError) => {
reject(error) // 处理请求错误
})
})
}
// 全部导出
export { instance, post, fetch, pending, del, removePending, removeOtherPending }
以上大致封装完毕,导出相关用法。
二,在你项目结构中所适用的位置创建 index.ts 文件,我是在apis 目录下创建的。
// 引入上文index.ts 文件 可以决定路径,也可@/...(@代表src下)。
import {instance, removePending, post, fetch, del, pending,} from '这里是你上个文件创建的位置'
import { ElMessage } from 'element-plus'
// ts中 axios 类型
import { AxiosResponse, AxiosError } from 'axios'
// 这里是在外部文件 处理的baseUrl 基准地址,你也可以在上文中就约定好,一般基准地址都是动态的,不手动修改的
import * as base from './base'
import router from '@/router'
const instanceInit = () => {
// 在这设置了基准地址
instance.defaults.baseURL = base.baseURL
//
instance.interceptors.response.use(
(response: AxiosResponse) => {
removePending(response.config) // 在一个ajax响应后再执行一下取消操作,把已经完成的请求从pending中移除
if (response.data.code === 401 || response.data.code === '401') {
ElMessage({
type: 'warning',
message: response.data.msg || '登录信息已过期,请重新登录!',
})
router.replace({path: '/login'})
return Promise.reject()
}
return response
},
(error: AxiosError) => {
// 当前接口不需要提示
if (!error.config?.params?.noWarning) {
ElMessage({
type: 'warning',
message: '系统错误,请联系管理员!',
})
}
return Promise.reject(error)
}
)
}
export { instanceInit, instance, removePending, post, del, fetch, pending }
三,在 main.ts 中引入:
// 引入 上文声明 instanceInit 方法
import { instanceInit } from './apis/index'
instanceInit()
以上就是完整封装的axios, 里面包含注释。 如要登录后设置 请求头token, 可直接在拿到token后直接设置。
import { instance } from '@/apis/index'
instance.defaults.headers.common.Authorization = '你的token'
四,下面来看一下使用示例:
首先可以分业务类型,功能模块去区分各个不同文件。在此就创建一个 equipment.ts 文件。文件中定义不同路径请求的api。可直接在 组件中引入使用。
// 引入封装好的 get post 请求
import { fetch, post } from './index'
export const updateSuspectNoItemYet = {
r: (params: any) => fetch('/suspect/updateSuspectNoItemYet', params),
}
export const listGoodsPage = {
r: (params: any) => post('/goods/listGoodsPage', params, {
headers: {
// 这里设置 canMoreActive 说明该接口api 是可以并发的,多次请求。(也可在此配置 axios官网 所说的配置项
// eg: headers: { Authorization: 'Bearer 123' })
canMoreActive: 'canMoreActive',
// Authorization: 'Bearer 123'
},
}),
}
// 组件中 使用
import { listGoodsPage, updateSuspectNoItemYet } from '@/apis/equipment'
const getList = async () => {
// params 入参 {id:'1',name: '测试'}
const res = await listGoodsPage.r(params)
}
以上就是完整的示例,欢迎评论区讨论,如有写的不足的地方欢迎指出。感谢点赞,收藏!
原文地址:https://blog.csdn.net/weixin_50559423/article/details/142487540
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!