ts
src/service/request/type.ts
import type { AxiosRequestConfig, AxiosResponse } from 'axios'
// 针对AxiosRequestConfig配置进行扩展
export interface HYInterceptors<T = AxiosResponse> {
requestSuccessFn?: (config: AxiosRequestConfig) => AxiosRequestConfig
requestFailureFn?: (err: any) => any
responseSuccessFn?: (res: T) => T
responseFailureFn?: (err: any) => any
}
export interface HYRequestConfig<T = AxiosResponse> extends AxiosRequestConfig {
interceptors?: HYInterceptors<T>
}
ts
import axios from 'axios'
import type { AxiosInstance } from 'axios'
import type { HYRequestConfig } from './type'
// 拦截器: 蒙版Loading/token/修改配置
/**
* 两个难点:
* 1.拦截器进行精细控制
* > 全局拦截器
* > 实例拦截器
* > 单次请求拦截器
*
* 2.响应结果的类型处理(泛型)
*/
class HYRequest {
instance: AxiosInstance
// request实例 => axios的实例
constructor(config: HYRequestConfig) {
this.instance = axios.create(config)
// 为所有的instance实例都添加拦截器
this.instance.interceptors.request.use(
(config) => {
// 可以添加: loading/token/headers
return config
},
(err) => {
return err
}
)
this.instance.interceptors.response.use(
(res) => {
return res.data
},
(err) => {
return err
}
)
// 针对特定的hyRequest实例添加拦截器
this.instance.interceptors.request.use(
config.interceptors?.requestSuccessFn,
config.interceptors?.requestFailureFn
)
this.instance.interceptors.response.use(
config.interceptors?.responseSuccessFn,
config.interceptors?.responseFailureFn
)
}
// 封装网络请求的方法
// T => IHomeData
request<T = any>(config: HYRequestConfig<T>) {
// 单次请求的成功拦截处理, 单个请求的拦截器,需要自己手动调用,拦截的本质就是在特定的时候调用,请求拦截器,就是在发送网络请求之前调用。响应拦截器就是在得到后端的结果返回到前台前调用
if (config.interceptors?.requestSuccessFn) {
config = config.interceptors.requestSuccessFn(config)
}
// 返回Promise
return new Promise<T>((resolve, reject) => {
this.instance
.request<any, T>(config)
.then((res) => {
// 单词响应的成功拦截处理
if (config.interceptors?.responseSuccessFn) {
// 重新指定响应结果
res = config.interceptors.responseSuccessFn(res)
}
resolve(res)
})
.catch((err) => {
reject(err)
})
})
}
get<T = any>(config: HYRequestConfig<T>) {
return this.request({ ...config, method: 'GET' })
}
post<T = any>(config: HYRequestConfig<T>) {
return this.request({ ...config, method: 'POST' })
}
delete<T = any>(config: HYRequestConfig<T>) {
return this.request({ ...config, method: 'DELETE' })
}
patch<T = any>(config: HYRequestConfig<T>) {
return this.request({ ...config, method: 'PATCH' })
}
}
export default HYRequest
ts
src/service/index.ts
import { BASE_URL, TIME_OUT } from './config'
import HYRequest from './request'
const hyRequest = new HYRequest({
baseURL: BASE_URL,
timeout: TIME_OUT,
})
const hyRequest2 = new HYRequest({
baseURL: BASE_URL,
timeout: TIME_OUT,
// 针对hyRequest2实例的特定的请求拦截
interceptors: {
requestSuccessFn: (config) => {
return config
}
}
})
export { hyRequest, hyRequest2}
ts
src/service/modules/login.ts
import hyRequest from '..'
export function accountLogin(account: any) {
return hyRequest.post({
url: '/login',
data: account,
// 单个请求的拦截器编写位置
interceptors:{
// 请求成功的拦截器回调
responseSuccessFn(config){
return config
}
}
})
}
请求拦截器可以编写多个。执行顺序于编写顺序有关,越早编写。请求拦截器就越先执行。响应拦截器的执行顺序与请求拦截器的执行顺序相反
js
拦截器知识点介绍
// 一般在使用axios时,会用到拦截器的功能,一般分为两种:请求拦截器、响应拦截器。
// 请求拦截器
// 在请求发送前进行必要操作处理,例如添加统一cookie、请求体加验证、设置请求头等,相当于是对每个接口里相同操作的一个封装;
// 响应拦截器
// 同理,响应拦截器也是如此功能,只是在请求得到响应之后,对响应体的一些处理,通常是数据统一处理等,也常来判断登录失效等。
// 配置全局请求拦截器
// 请求拦截器就是对config进行操作的,然后返回新的config
// axios.interceptors.request.use(请求成功的拦截回调函数,请求失败的拦截回调函数)
axios.interceptors.request.use(
(config) => {
//config是请求时的配置信息,里面包含很多关于请求的信息
// config.url 请求地址、config.headers.xxx = yyy 添加请求头
// 请求拦截的常用操作
// 可以对原来的配置进行一些修改:
// 1. header
// 2. 认证登录: token/cookie
// 3. 请求参数进行某些转化
// 举例:
// 看一下哪些请求需要验证token,哪些不需要
// 通过配置文件配置白名单(不需要验证)
const whiteListApi = ["/a", "/b"]
// TOEKN存在于localstorage中
// 获取请求地址:config.url
if (!whiteListApi.includes(config.url)) {
// 需要验证token
} else {
}
// 也可以设置 发送请求时的等待loading动画
console.log("请求成功的拦截")
return config
},
(err) => {
console.log("请求失败的拦截")
return err
}
)
// 配置全局响应拦截器
// 响应拦截器就是对res进行操作的, 然后返回新的res
// axios.interceptors.response.use(请求成功的拦截回调函数,请求失败的拦截回调函数)
axios.interceptors.response.use(
(res) => {
// res是请求获得的结果
// 响应拦截的常用操作:
// 可以对res数据进行处理, 再返回数据
// 也可以设置请求结束loading动画
console.log("响应成功的拦截")
return res.data
},
(err) => {
console.log("响应失败的拦截:", err)
return err
}
)
axios
.get("http://123.207.32.32:9001/lyric?id=500665346")
.then((res) => {
console.log("res:", res)
})
.catch((err) => {
console.log("err:", err)
})
js
封装axiosd的必要性
import axios from "axios"
// axios就是axios库默认提供给我们的实例对象
// axios.defaults.xxx 设置的式全局配置,对于所有的axios实例都可见
// 每个实例都是单独, 不会与其他的axios实例的配置(baseURL,TIMEOUT、headers)发生冲突
// 每个实例对象的配置可以设置不同,互不干扰
// const axios实例对象 = axios.create({单独的配置})
const instance1 = axios.create({
baseURL: "http://123.207.32.32:9001",
timeout: 6000,
headers: {}
})
const instance2 = axios.create({
baseURL: "http://123.207.32.32:8000",
timeout: 10000,
headers: {}
})
// 使用实例1发生请求
instance1.get("/lyric", {
params: {
id: 500665346
}
}).then(res => {
console.log("res:", res.data)
})