返回

再议二次封装一个请求工具类

前端

背景

在项目开发过程中,除了原生 fetch API,我一直使用两个request 框架:axios 和 阿里的useRequest。

由于项目大多为后台管理系统,自然免不了大量HTTP请求,于是我便基于原生Fetch API封装了一个请求工具类。这个类提供了诸如get、post、put、delete等方法,并且支持链式调用,用起来非常方便。

契机

随着项目的不断发展,我对这个请求工具类也提出了更高的要求。比如:

  • 支持超时和重试。
  • 支持自动重定向。
  • 支持请求头和请求参数的定制化配置。
  • 支持请求和响应的拦截。

原生的请求工具类无法满足这些需求,于是我决定对它进行二次封装。

设计

二次封装的主要思路是,在原有请求工具类基础上,新增一个Request类,该类负责处理超时、重试、重定向等通用逻辑。同时,保留原有工具类的所有方法,并对部分方法进行重写,以支持请求头和请求参数的定制化配置。

Request类的设计如下:

export class Request {
  constructor(config: RequestConfig) {
    this.config = config;
  }

  get<T>(url: string, config?: RequestConfig): Promise<T> {
    return this.request('GET', url, config);
  }

  post<T>(url: string, data?: any, config?: RequestConfig): Promise<T> {
    return this.request('POST', url, data, config);
  }

  put<T>(url: string, data?: any, config?: RequestConfig): Promise<T> {
    return this.request('PUT', url, data, config);
  }

  delete<T>(url: string, config?: RequestConfig): Promise<T> {
    return this.request('DELETE', url, config);
  }

  request<T>(method: string, url: string, data?: any, config?: RequestConfig): Promise<T> {
    // 处理超时、重试、重定向等通用逻辑
    // ...

    // 请求和响应的拦截
    // ...

    return fetch(url, {
      method,
      headers: this.config.headers,
      body: data,
      ...config,
    }).then(res => {
      // 处理请求和响应的拦截
      // ...

      return res.json();
    });
  }
}

RequestConfig接口的设计如下:

export interface RequestConfig {
  headers?: HeadersInit;
  params?: any;
  timeout?: number;
  retry?: number;
  redirect?: 'follow' | 'manual' | 'error';
}

使用

二次封装后的请求工具类,使用起来非常简单。只需要创建一个Request实例,然后调用相应的方法即可。

const request = new Request({
  headers: {
    'Content-Type': 'application/json',
  },
  timeout: 10000,
  retry: 3,
  redirect: 'follow',
});

request.get('/api/users').then(res => {
  console.log(res);
});

总结

二次封装请求工具类,可以使我们的代码更加整洁、优雅,并且提高开发效率。

希望本文对您有所帮助。如果您有任何问题,请随时留言。