请求几个关于 ts 封装 axios 的问题 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
zzlit
V2EX    程序员

请求几个关于 ts 封装 axios 的问题

  •  
  •   zzlit 2021-02-20 12:25:32 +08:00 3027 次点击
    这是一个创建于 1744 天前的主题,其中的信息可能已经有所发展或是发生改变。

    小弟第一次用 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 条附言    2021-03-01 17:26:38 +08:00
    Durandal01 大佬指点了一下 `axios.post<DataType, DataType>() 第二个泛型参数就是实际返回的类型。`,我才发现原来之前这种写法 axios({method: 'post'})的是没有的,需要用`axios.post()`,这里才能定义两个参数,例如 get:
    ```
    get<T = any, R = AxiosResponse<T>>(url: string, config?: AxiosRequestConfig): Promise<R>;

    ```

    但是实际上如果用的时候还是返回了 AxiosResponse 声明的东西,但的确是定义了参数,所以就从 Pyrex23 大佬提供的博文还是重新声明了一下
    ```
    get<T = any>(url: string, config?: AxiosRequestConfig): Promise<T>;
    ```

    这样返回的就不是 AxiosResponse 声明的东西而是自己定义的了,所以我在用的时候下面这样

    ```
    interface ApiResponse<T, R> {
    (param: T): Promise<R>;
    }

    const apiMethod: ApiResponse<参数类型, 返回类型> = params => {
    return post<返回类型>(HOSPITALBASE.UPLOAD_DEVICE_ID, params);
    };
    ```
    这样就可以在用 apiMethod 这个方法的时候自动推导出定义的返回类型里面的内容了,如果有能更好的处理方法后面再更新,第二个问题还没有找到好的处理办法。
    7 条回复    2021-02-24 08:56:38 +08:00
    Pyrex23
        1
    Pyrex23  
       2021-02-20 12:34:09 +08:00 via iPhone   2
    第一个问题 前两天也遇到了类似的 最后用泛型解决了,可以参考一下这篇文章

    https://gaojiajun.cn/2019/12/typescript-axios-interceptor-commondata/
    zzlit
        2
    zzlit  
    OP
       2021-02-20 13:42:38 +08:00
    @Pyrex23 我也看到了这篇,处理方法就不是我种在成功的时候就已经处理完 code 把 data 返回了,是在使用的时候去处理 code,其实我看了 github 上几个项目基本都是这样处理的,的确比我目前这种要好一点,作为了一个我的主要备选方案了
    zzlit data-uid=
        3
    zzlit  
    OP
       2021-02-20 13:46:40 +08:00
    而且我下面的说的重新声明 AxiosRequestConfig 就是看到这边重新声明了一个 AxiosInstance 感觉是可以实现作为参数加到请求去而不是放在 headers 里面
    Durandal01
        4
    Durandal01  
       2021-02-20 15:33:11 +08:00
    @zzlit

    1. 以 post 为例: axios.post<DataType, DataType>() 第二个泛型参数就是实际返回的类型。

    2. 没搞懂你为什么要这么做。能描述一下场景吗?
    zzlit
        5
    zzlit  
    OP
       2021-02-20 16:52:50 +08:00
    @Durandal01 你好~

    首先第一点:post 的例子的第二个泛型参数这是上面提到的文章里面我看到重新对 AxiosInstance 声明才有的吧?原来的话只有只一个的泛型参数的;

    然后问题二的场景是:我有一些请求接口需要 loading,有一些需要 token,有一些又需要返回带 code 的参数(因为我现在的处理是把 code 统一处理了,成功的返回就是直接的 data ),所以我就定义了一个 extraconfig 参数想在请求接口的时候带进来,然后在请求拦截器和响应拦截器里面都需要去做一些操作,场景就是这样的。
    Durandal01
        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 也不可能添加一个它自己用不到的参数 :)
    myCupOfTea
        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;
    这两行我用不到 所以没有修改声明
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     795 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 37ms UTC 20:22 PVG 04:22 LAX 12:22 JFK 15:22
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86