小弟第一次用 ts 写项目,之前都是写一些 demo,下面有几个关于 axios 封装的问题,请求大佬们指点一下,感激不尽!
第一个问题是我在响应拦截里面做了一下处理,因为用的时候有的需要返回 code 以应对不同的情况,有的不需要直接用 data,就导致了不好定义req
这个方法返回的类型,在使用的时候res.
出来的是 axios 定义的 AxiosResponse 里面的东西,我想让它提示我返回的 data 里面自己定义的类型
或者是 没有 data 时候的 boolean
?
// 后端返回的格式
{
code: 0,
data: xxx,
errorMsg: xxx
}
// 使用的时候
const req = async (params: any) => {
const res = await post(url, params);
/** res.出来的提示是 AxiosResponse<any>的这些东西,axios 声明的如下
export interface AxiosResponse<T = any> {
data: T;
status: number;
statusText: string;
headers: any;
config: AxiosRequestConfig;
request?: any;
}
*/
};
request.interceptors.request.use(
config => {
const headers = config.headers;
const { extraConfig } = headers;
if (extraConfig) {
const { needLoading, needToken } = extraConfig;
if (needLoading) // loading
if (needToken) // token
}
return config;
},
error => {
return Promise.reject(error);
}
);
request.interceptors.response.use(
response => {
if (response.config.headers.extraConfig.needHandleError) {
// 需要返回 code 以应对不同的情况
return Promise.resolve(response.data);
}
const { data, errorMsg, code } = response.data;
if (code === '00000') {
if (data === null || data === undefined) {
return Promise.resolve(true);
} else {
return Promise.resolve(data);
}
} else {
return Promise.reject(new Error(errorMsg || 'Error'));
}
},
error => {
return Promise.reject(error);
}
);
第二个问题就是我要配置一些自定义的内容进去,直接写在request
的参数里面不行,因为AxiosRequestConfig
没有定义这个额外的配置参数所以我的做法是写在了headers
里面,这样就导致了请求的时候网页上也会看到我写的这个extraConfig: [object, object]
,我是不想看到这个的,我想到的一个是不是重新定义AxiosRequestConfig
?这个该怎么写呢?
interface Config {
needLoading?: boolean;
needToken?: boolean;
needHandleError?: boolean;
}
const dealConfig = (extraConfig?: Config) => {
const defaultExtraConfig = {
needLoading: true,
needToken: true,
needHandleError: false
};
if (typeof extraConfig === 'undefined') {
extraConfig = defaultExtraConfig;
} else {
Object.keys(defaultExtraConfig).forEach(key => {
if (!Object.prototype.hasOwnProperty.call(extraConfig, key)) {
(extraConfig as Config)[key] = defaultExtraConfig[key];
}
});
}
return extraConfig;
};
export function post(url: string, params: object, extraConfig?: Config) {
extraConfig = dealConfig(extraConfig);
return request({
url,
method: 'post',
data: params,
headers: {
extraConfig
}
});
}
1
Pyrex23 2021-02-20 12:34:09 +08:00 via iPhone 2
第一个问题 前两天也遇到了类似的 最后用泛型解决了,可以参考一下这篇文章
https://gaojiajun.cn/2019/12/typescript-axios-interceptor-commondata/ |
2
zzlit OP @Pyrex23 我也看到了这篇,处理方法就不是我种在成功的时候就已经处理完 code 把 data 返回了,是在使用的时候去处理 code,其实我看了 github 上几个项目基本都是这样处理的,的确比我目前这种要好一点,作为了一个我的主要备选方案了
|
3
zzlit OP 而且我下面的说的重新声明 AxiosRequestConfig 就是看到这边重新声明了一个 AxiosInstance 感觉是可以实现作为参数加到请求去而不是放在 headers 里面
|
4
Durandal01 2021-02-20 15:33:11 +08:00
|
5
zzlit OP @Durandal01 你好~
首先第一点:post 的例子的第二个泛型参数这是上面提到的文章里面我看到重新对 AxiosInstance 声明才有的吧?原来的话只有只一个的泛型参数的; 然后问题二的场景是:我有一些请求接口需要 loading,有一些需要 token,有一些又需要返回带 code 的参数(因为我现在的处理是把 code 统一处理了,成功的返回就是直接的 data ),所以我就定义了一个 extraconfig 参数想在请求接口的时候带进来,然后在请求拦截器和响应拦截器里面都需要去做一些操作,场景就是这样的。 |
6
Durandal01 2021-02-20 20:30:16 +08:00 1
@zzlit
https://github.com/axios/axios/blob/master/index.d.ts#L140-L146 看这里,并不需要重新声明 instance ; 第二个可以考虑下通过 path 或者别的什么预先声明 interceptor 的处理函数,这样就不依赖外部传入的参数了。如果一定要采用命令式的方式,可以考虑下 transferRequest 和 transferResponse 参数。 从我个人的观点来说,axios 也不可能添加一个它自己用不到的参数 :) |
7
myCupOfTea 2021-02-24 08:56:38 +08:00
我直接 as 重新声明了下类型
```ts type MyResponse<T = any> = T; const request = axios.create({ baseURL: `/${apiPrefix || ''}`, }) as { (config: AxiosRequestConfig): AxiosPromise; (url: string, config?: AxiosRequestConfig): AxiosPromise; defaults: AxiosRequestConfig; interceptors: { request: AxiosInterceptorManager<AxiosRequestConfig>; response: AxiosInterceptorManager<MyResponse>; }; getUri(config?: AxiosRequestConfig): string; request<T = ReqResponse, R = MyResponse<T>>( config: AxiosRequestConfig, ): Promise<R>; get<T = ReqResponse, R = MyResponse<T>>( url: string, config?: AxiosRequestConfig, ): Promise<R>; delete<T = ReqResponse, R = MyResponse<T>>( url: string, config?: AxiosRequestConfig, ): Promise<R>; head<T = ReqResponse, R = MyResponse<T>>( url: string, config?: AxiosRequestConfig, ): Promise<R>; options<T = ReqResponse, R = MyResponse<T>>( url: string, config?: AxiosRequestConfig, ): Promise<R>; post<T = ReqResponse, R = MyResponse<T>>( url: string, data?: any, config?: AxiosRequestConfig, ): Promise<R>; put<T = ReqResponse, R = MyResponse<T>>( url: string, data?: any, config?: AxiosRequestConfig, ): Promise<R>; patch<T = ReqResponse, R = MyResponse<T>>( url: string, data?: any, config?: AxiosRequestConfig, ): Promise<R>; }; ``` (config: AxiosRequestConfig): AxiosPromise; (url: string, config?: AxiosRequestConfig): AxiosPromise; 这两行我用不到 所以没有修改声明 |