5、响应结果的类型处理
在modules/entire.ts中已经能够获得响应的数据,目前获得的数据是没有数据的类型的,因此什么操作也做不了,因此应配置其类型
interface IHighScoreData {
list: any[];
subtitle: string;
title: string;
type: string;
_id: string;
}
// 将类型传入request
hdRequest2
.request<IHighScoreData>({
url: "/home/highscore",
interceptors: {
requestSuccessFn: (config) => {
console.log("/home/highscore请求成功的拦截");
return config;
},
responseSuccessFn: (res) => {
console.log("/home/highscore响应成功的拦截");
console.log(res);
return res;
},
},
})
.then((res) => {
// 9、这里结果就能使用IHighScoreData类型了
console.log(res._id);
});
对于request/index.ts
import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from "axios";
interface HDInteceptors<T> {
requestSuccessFn?: (config: AxiosRequestConfig) => AxiosRequestConfig;
requestFailureFn?: (err: any) => any;
// 6、原来的responseSuccessFn返回值为AxiosResponse,需配置responseSuccessFn的返回值为T
responseSuccessFn?: (res: T) => T;
responseFailureFn?: (err: any) => any;
}
// 7、配置T的默认值为AxiosResponse
interface HDRequestConfig<T = AxiosResponse> extends AxiosRequestConfig {
interceptors?: HDInteceptors<T>;
}
class HDRequest {
// 创建这个类的目的:每个创建出的HDRequest的实例都对应一个axios实例
// 创建实例的方法:constructor()构造实例
instance: AxiosInstance;
constructor(config: HDRequestConfig) {
this.instance = axios.create(config);
// 添加全局拦截器,每个实例都有
this.instance.interceptors.request.use(
(config) => {
console.log("全局请求成功的拦截");
return config;
},
(err) => {
console.log("全局请求失败的拦截");
return err;
}
);
this.instance.interceptors.response.use(
(res) => {
console.log("全局响应成功的拦截");
// 1、在这里提取出响应数据中的data,那么在此之后的拦截器拦截到的数据就是res.data
return res.data;
},
(err) => {
console.log("全局响应失败的拦截");
return err;
}
);
// 针对特定的hdRequest实例添加拦截器
this.instance.interceptors.request.use(
config.interceptors?.requestSuccessFn,
config.interceptors?.requestFailureFn
);
this.instance.interceptors.response.use(
config.interceptors?.responseSuccessFn,
config.interceptors?.requestFailureFn
);
}
// 二次封装网络请求的方法
// 2、request<T = any>使得hdRequest2.request<IHighScoreData>操作能够通过传入结果的类型
// 8、HDRequestConfig<T>将结果类型传递给responseSuccessFn
request<T = any>(config: HDRequestConfig<T>) {
// 为同一个request实例的不同网络请求设置不同的拦截器
// 不能将拦截器放在实例上,这样的话同一个实例的拦截器都是一样的了
// 只能判断传进来的config中是否设置了拦截器,若设置了就直接执行
if (config.interceptors?.requestSuccessFn) {
//立即调用拦截器函数执行requestSuccessFn
config = config.interceptors.requestSuccessFn(config);
}
// 3、Promise<T>可以使得返回值类型为T
return new Promise<T>((resolve, reject) => {
this.instance
// 5、配置request<any, T>使得返回值类型为T
// 因此需要配置config.interceptors.responseSuccessFn的返回值类型,见第6步
.request<any, T>(config)
.then((res) => {
if (config.interceptors?.responseSuccessFn) {
// 当前的res是this.instance.request(config)的返回值,其类型不是T,因此应通过第5步进行配置
res = config.interceptors.responseSuccessFn(res);
}
// 4、由于Promise<T>,那么当前的res类型应为T
resolve(res);
})
.catch((err) => {
reject(err);
});
});
}
get<T = any>(config: HDRequestConfig<T>) {
return this.request({ ...config, method: "GET" });
}
post<T = any>(config: HDRequestConfig<T>) {
return this.request({ ...config, method: "POST" });
}
delete<T = any>(config: HDRequestConfig<T>) {
return this.request({ ...config, method: "DELETE" });
}
patch<T = any>(config: HDRequestConfig<T>) {
return this.request({ ...config, method: "PATCH" });
}
}
export default HDRequest;