内置功能
自定义请求别名 new
new
sluggard-http 支持自定义请求别名
- 可设置新的请求别名以抽离 对 请求体 / 响应体 进行统一修改的场景
- 亦可以对原始请求别名(
GET
/POST
/PUT
/DELETE
...)进行重构
类型
ts
interface MethodAlias {
[aliasName: string]: {
axiosMethod: AxiosMethodsName
handle: MethodAliasHandle
}
}
type MethodAliasHandle = (...params: any[]) => any[]
示例 - 修改请求体的别名
通常发起一个下载文件请求时, 都需要在请求体中添加 responseType: 'blob'
可以创建一个 download别名, 调用此别名时发起 post请求
并自动携带 responseType: 'blob'参数
可以创建一个 download别名, 调用此别名时发起 post请求
并自动携带 responseType: 'blob'参数
ts
import type { RequestConfig } from 'sluggard-http'
import { Http } from 'sluggard-http'
const methodAlias = {
// 👇 要新建的别名名称
download: {
// 此别名实际上调用的 axios 方法
axiosMethod: 'post',
// 别名处理函数
handle: (url: string, data: any, config: RequestConfig) => {
// 为请求体添加 responseType 参数
return [url, data, { ...config, responseType: 'blob' }]
},
},
} as const // 此处获取字面量类型,有助于ts类型推导
// 创建 http 实例 传入 typeof methodAlias 泛型,使 http.download() 能够自行推导类型
export const http = Http.create<typeof methodAlias>(
{
baseURL: '...',
timeout: 1000,
headers: {'Authorization': '...'}
},
{
methodAlias,
life: { ... },
}
)
handle
详解- 接受任意参数,
handle
的参数即为你所新增别名的参数 - 返回一个数组, 该数组将作为
实际上调用的 axios 方法
的参数传入
- 接受任意参数,
效果
- 上述代码将新增一个
download
别名并挂载到http
实例上 - 通过
http.download()
即可调用,调用时实际等于执行了以下伪代码
ts
http.download(url, data, config){
// 调用你定义的 handle 函数, 为请求体添加 responseType 参数
const [url, data, config] = handle(url, data, config)
// 返回实际调用的 axios 方法
return http.post(url, data, config)
}
示例 - 修改响应体的别名
假设后端返回的数据采用 { code: number, data: any, msg: string }结构
可以创建一个 data别名,调用此别名时发起 post请求
并判断 response.data.code是否为 200, 是则直接返回 response.data.data承载的数据体
可以创建一个 data别名,调用此别名时发起 post请求
并判断 response.data.code是否为 200, 是则直接返回 response.data.data承载的数据体
⚠️ 用于修改响应体的别名需要与 响应拦截器 配合使用
ts
import type { MethodAlias, RequestConfig } from 'sluggard-http'
import { Http } from 'sluggard-http'
const methodAlias = {
data: {
axiosMethod: 'post',
handle: (url: string, data: any, config: RequestConfig) => {
// 在 RequestConfig 中添加一个 postType 标识符, 用于在响应拦截器中捕获此请求
return [url, data, { ...config, postType: "postData" }]
},
},
} as const
// 创建 http 实例
...
ts
// 配合响应拦截器使用
http.interceptorsResponseUse((response) => {
// ...
if (
response.config.postType === 'postData' // 捕获由 data 别名发起的请求
&& response.data.code === 200 // 判断 code 值
){
return response.data.data // 直接返回 data 字段承载的数据体
}
// ...
return response
})
效果
- 上述代码将新增一个
data
别名并挂载到http
实例上 - 通过
http.data()
即可调用 - 当
http.data()
请求成功且响应体的code
字段为200
时, 直接返回响应体的data
字段数据
示例 - 重构原有请求别名
通常发送请求数据时,需要清除数据中 字符串类型字段的头尾空格
可以重构原有的 post别名,增加去除头尾空格的功能
可以重构原有的 post别名,增加去除头尾空格的功能
ts
import type { MethodAlias, RequestConfig } from 'sluggard-http'
import { Http } from 'sluggard-http'
import { clearTrim } from "utils" // 引入一个你定义的用于去除字符串头尾空格的工具
const methodAlias = {
// 👇 将重构原别名
post: {
axiosMethod: 'post',
handle: (url: string, data: any, config: RequestConfig) => {
// 调用去除空格工具函数
clearTrim(config)
return [url, data, config]
},
},
} as const
// 创建 http 实例
...
效果
- 上述代码将修改
http
实例原有的post
别名 - 调用
http.post()
时会自动去除请求体中字符串字段数据
的头尾空格
请求控制 new
new
请求更新
在当前请求处于 进行中时, 若发起 相同请求, 则会触发请求更新,取消之前未完成的相同请求, 避免重复请求
e.g.
连续发起两个相同
请求TSconst get1 = http.get('/user?ID=12345') setTimeout(()=>{ const get2 = http.get('/user?ID=12345') },200)
若
get1
在200ms内未请求完成,get2
发起请求时,get1
将被取消
具体业务场景 👇
利用 sluggard-http 的请求更新机制
- 无需从交互层面进行控制,sluggard-http 发起
相同
请求时,会自动取消
之前未完成的相同请求,避免问题发生 - 且对
相同
的定义可以自行设置级别。例如此处,无论用户携带的过滤查询条件是什么,只要是点击查询发起的,都应当视为相同请求。所以只需校验请求方式
&请求地址
,相同便视为相同请求
- 此时将级别配置为
path
即可👇(默认为all
,无需配置)
- 无需从交互层面进行控制,sluggard-http 发起
使用方法
发起请求时在
RequestConfig
(继承自AxiosRequestConfig
)中添加updateLevel: "path"
ts
export async function getList(data: any) {
const httpRes = await http.post(
"/getList",
data,
{ updateLevel: "path" } // RequestConfig
);
return httpRes;
}
updateLevel
有all
、path
、free
三个级别,详见 RequestConfig
全局请求清除
清除并 取消当前所有的请求, 往往在 路由变化时使用
- sluggard-http 提供
clearPending()
方法,用于清除当前还未完成的所有请求
当用户进行页面切换时,若之前页面存在还 未完成的请求, 可将其清除,以节省请求资源
ts
// 以 vueRouter 为例,在路由守卫中进行配置
router.afterEach(() => {
http.clearPending(); // 清除所有还未完成的请求
});
- 如果某些请求需要设置不被清除,可在请求中单独配置
发起请求时在
RequestConfig
(继承自AxiosRequestConfig
)中添加canNotClear: true
即可
ts
export async function getList(data: any) {
const httpRes = await http.post("/getList", data, {
// 此请求不会被 clearPending() 清除
canNotClear: true
});
return httpRes;
}
请求拦截
对还在 进行中的 指定请求进行拦截, 并 取消请求
请求拦截无视
RequestConfig
的canNotClear
属性
- sluggard-http 提供
abortPending()
方法,用于根据指定条件来拦截请求abortPending()
方法接收一个abortSign
参数,该参数可以是一个拦截标识符字符串
,也可以是一个请求标识数组
拦截标识符通过请求返回的 HttpPromise对象获取(继承自 axios的响应Promise对象)
ts
// 从请求 HttpPromise 对象中获取拦截标识符 abortSignUuidCode
const { abortSignUuidCode } = http
.post("/getList", { size: 10, current: 1 })
.then(function (response) {
// ...
})
.catch(function (error) {
// ...
})
.finally(function () {
// ...
});
// 通过 abortSignUuidCode 拦截请求
http.abortPending(abortSignUuidCode)
当无法获取 拦截标识符时,可以通过 [请求方式, 请求地址, 请求参数]格式组成的请求标识数组来拦截请求
ts
http
.post("/getList", { size: 10, current: 1 })
.then(function (response) {
// ...
})
.catch(function (error) {
// ...
})
.finally(function () {
// ...
});
// 通过 [请求方式, 请求地址, 请求参数] 组成的请求标识数组来拦截请求
http.abortPending(["post", "/getList", { size: 10, current: 1 }]);
进度生命周期 new
new
sluggard-http 支持在单个请求开始
/全部请求结束
时抛出钩子函数
- 常与
NProgress
等进度条插件配合使用
类型
ts
/**
* 请求进度的生命周期
* begin: 有请求开始时触发
* end: 全部请求结束时触发
*/
interface LifeType {
begin?: (config: HttpConfig) => void
end?: () => void
}
示例 - 显示请求进度条
ts
import NProgress from "nprogress";
import { Http } from 'sluggard-http'
export const http = Http.create(
{
baseURL: '...',
timeout: 1000,
headers: {'Authorization': '...'}
},
{
methodAlias: { ... },
life: {
begin: () => {
NProgress.start()
},
end: () => {
NProgress.done()
},
},
}
)