简体   繁体   English

Typescript axios 分型

[英]Typescript axios typings

This is my first question, so let me know how I can improve.这是我的第一个问题,所以让我知道如何改进。

I have the following axios fetch function:我有以下 axios 获取 function:

export enum RequestMethod {
  GET = 'GET',
  POST = 'POST',
  PUT = 'PUT',
  PATCH = 'PATCH',
  DELETE = 'DELETE',
}

export const fetchAxiosAPI = async (
  url: string,
  method: RequestMethod,
  data = {},
  options = {}
) => {
  let result;
  try {
    result = await axios({
      method,
      url: `${process.env.REACT_APP_API_URL}/${url}`,
      data,
      ...options,
      validateStatus: () => {
        return true;
      },
    }).then(response => response.data);
  } catch (err) {
    return null;
  }
  const errorStatus = result.error.status;
  if (errorStatus === 401) {
    localStorage.removeItem('access_token');
    history.push('/login');
  }
  if (errorStatus === 404) {
    history.replace(NOT_FOUND);
  }
  if (errorStatus === 500) {
    history.replace(INTERNAL_SERVER_ERROR);
  }
  return result;
};

It looks ugly, uses await and then (which we shouldn't use).它看起来很丑,使用 await 和 then (我们不应该使用)。 I have two questions:我有两个问题:

  1. How can I pass a typescript generic into this function as a parameter that will infer typescript typings for the response of API call (Promise)? How can I pass a typescript generic into this function as a parameter that will infer typescript typings for the response of API call (Promise)? I found and example using axios[methodName] like:我找到了使用 axios[methodName] 的示例,例如:

axios.get<User[]>(url) axios.get<用户[]>(网址)

But haven't found a method to pass generic using general axios method like provided in my code example.但是还没有找到像我的代码示例中提供的那样使用通用 axios 方法传递泛型的方法。

  1. How to handle error statuses, catch block and await/then - use 1 of them?如何处理错误状态、捕获块和等待/然后 - 使用其中的 1 个? Basically, how to rewrite fetchAxiosAPI function.基本上,如何重写fetchAxiosAPI function。

If I'm reading the documentation and index.d.ts file correctly, axios.request should do it.如果我正确阅读了文档和index.d.ts文件, axios.request应该这样做。 From the docs:从文档:

For convenience aliases have been provided for all supported request methods.为方便起见,已为所有受支持的请求方法提供了别名。

axios.request(config)

... ...

and in index.d.ts :index.d.ts中:

 export interface AxiosInstance { (config: AxiosRequestConfig): AxiosPromise; (url: string, config?: AxiosRequestConfig): AxiosPromise; defaults: AxiosRequestConfig; interceptors: { request: AxiosInterceptorManager<AxiosRequestConfig>; response: AxiosInterceptorManager<AxiosResponse>; }; getUri(config?: AxiosRequestConfig): string; request<T = any, R = AxiosResponse<T>> (config: AxiosRequestConfig): Promise<R>; get<T = any, R = AxiosResponse<T>>(url: string, config?: AxiosRequestConfig): Promise<R>; delete<T = any, R = AxiosResponse<T>>(url: string, config?: AxiosRequestConfig): Promise<R>; head<T = any, R = AxiosResponse<T>>(url: string, config?: AxiosRequestConfig): Promise<R>; options<T = any, R = AxiosResponse<T>>(url: string, config?: AxiosRequestConfig): Promise<R>; post<T = any, R = AxiosResponse<T>>(url: string, data?: any, config?: AxiosRequestConfig): Promise<R>; put<T = any, R = AxiosResponse<T>>(url: string, data?: any, config?: AxiosRequestConfig): Promise<R>; patch<T = any, R = AxiosResponse<T>>(url: string, data?: any, config?: AxiosRequestConfig): Promise<R>; } export interface AxiosStatic extends AxiosInstance { create(config?: AxiosRequestConfig): AxiosInstance; Cancel: CancelStatic; CancelToken: CancelTokenStatic; isCancel(value: any): boolean; all<T>(values: (T | Promise<T>)[]): Promise<T[]>; spread<T, R>(callback: (...args: T[]) => R): (array: T[]) => R; isAxiosError(payload: any): payload is AxiosError; } declare const axios: AxiosStatic;

Notice that request just accepts the config object like the axios function itself does, but unlike axios it has the generic type parameters you've seen used on get , post , and such. Notice that request just accepts the config object like the axios function itself does, but unlike axios it has the generic type parameters you've seen used on get , post , and such.

So something like this, see *** comments:所以像这样,见***评论:

export const fetchAxiosAPI = async <T>(
//                                 ^^^−−−−−−−−−−− *** type parameter
    url: string,
    method: RequestMethod,
    data = {},
    options = {}
) => {
    let result: T;
    try {
        // *** Get the response using `axios.request` with the type argument
        const response = await axios.request<T>({
            method,
            url: `${process.env.REACT_APP_API_URL}/${url}`,
            data,
            ...options,
            validateStatus: () => {
                return true;
            },
        });
        // *** Get the result
        result = response.data;
    } catch (err) {
        return null; // *** This is poor practice; allow the error to propagate
                     // or throw a new error
    }
    const errorStatus = result.error.status;
    if (errorStatus === 401) {
        localStorage.removeItem('access_token');
        history.push('/login');
    }
    if (errorStatus === 404) {
        history.replace(NOT_FOUND);
    }
    if (errorStatus === 500) {
        history.replace(INTERNAL_SERVER_ERROR);
    }
    return result;
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM