基于 Axios 的请求封装方案

标签:DX, TypeScript, axios
分类:技术
10分钟阅读

最前

正文

RestCoreVerAxios.ts
import axios, {
  AxiosHeaders,
  AxiosInstance,
  AxiosRequestConfig,
  RawAxiosRequestHeaders,
} from "axios";
import dayjs from "dayjs";
import RestCoreAbs from "./_RestCoreAbs"; /* 🎈 抽象类,服务于 RestCore / RestCoreVerAxios 的快速创建*/
// import ...

type AxiosValidHeaders = RawAxiosRequestHeaders | AxiosHeaders;

type PlainObj = Record<
  string,
  string | number | boolean | null | undefined
>;

enum ReqMethod {
  GET = "GET",
  POST = "POST",
  PUT = "PUT",
  PATCH = "PATCH",
  DELETE = "DELETE",
}

const headersPlainObj = {
  "response-format": "json",
  Accept: "*/*",
  "Accept-Encoding": "gzip, deflate",
  "Content-Type": "application/json;charset=utf-8",
};

class RestCoreVerAxios extends RestCoreAbs {
  private axiosInstance: AxiosInstance | null = null;
  private methodInConf: string = ReqMethod.GET;

  constructor(urlHeadPartial?: string, assignBaseUrl: string = "/api") {
    super()
    /* 这里 #urlPartialValidator 方法定义在 RestCoreAbs 中;方法定义也可见 RestCore 中实现 */
    RestCoreVerAxios.urlPartialValidator(urlHeadPartial);

    this.axiosInstance = axios.create({
      baseURL: assignBaseUrl + (urlHeadPartial || ""),
      headers: {
        "Ver-Use-Axios": "wow",
        ...headersPlainObj,
      },
    });
  }

  private setMethodInConf(method: ReqMethod) {
    this.methodInConf = method;
  }

  private bridgeToRestRequestWrpper(method: ReqMethod, url: string) {
    if (/^[\.|\/]{0,1}$/.test(url)) {
      url = "";
    }
    RestCoreVerAxios.urlPartialValidator(url);

    this.setMethodInConf(method);
    return new RestRequestWrapper(url, this);
  }

  public Post(url: string) {
    return this.bridgeToRestRequestWrpper(ReqMethod.POST, url);
  }

  public Get(url: string) {
    return this.bridgeToRestRequestWrpper(ReqMethod.GET, url);
  }

  public Put(url: string) {
    return this.bridgeToRestRequestWrpper(ReqMethod.PUT, url);
  }

  public Patch(url: string) {
    return this.bridgeToRestRequestWrpper(ReqMethod.PATCH, url);
  }

  public Delete(url: string) {
    return this.bridgeToRestRequestWrpper(ReqMethod.DELETE, url);
  }

  protected async GetResponseInternal<T>(
    url: string,
    headers: AxiosValidHeaders,
    data?: PlainObj,
    params?: PlainObj,
  ) {
    const conf4Axios: AxiosRequestConfig = {
      // axios config will auto merge
      url,
      method: this.methodInConf,
      headers,
      data,
      params,
    };

    const res = await (this.axiosInstance as AxiosInstance).request<T>(
      conf4Axios,
    );
    return res;
  }

  public async GetTResponse<T>(
    url: string,
    headers: AxiosValidHeaders,
    data?: PlainObj,
    params?: PlainObj,
  ) {
    const res = await this.GetResponseInternal<T>(url, headers, data, params);
    return res.data;
  }
}

export default RestCoreVerAxios;

其中,RestRequestWrapper 定义如下:

RestCoreVerAxios.ts
const RestDateTimeFormat = "YYYY-MM-DD HH:mm:ss";

class RestRequestWrapper {
  private readonly bodyPlainObj: PlainObj = Object.create(null);
  private readonly paramsPlainObj: PlainObj = Object.create(null);
  private axiosConfHeaders: AxiosValidHeaders = {};

  constructor(
    private readonly url: string,
    private readonly restCore: RestCoreVerAxios,
  ) {
    this.url = url;
    this.restCore = restCore;
  }

  public AddHeader(name: string, value: string) {
    if (!this.axiosConfHeaders) {
      this.axiosConfHeaders = new AxiosHeaders();
    }
    this.axiosConfHeaders[name] = value;
    return this;
  }

  public AddParameter(
    key: string,
    value: string | number | dayjs.Dayjs | boolean,
  ) {
    if (dayjs.isDayjs(value)) {
      value = value.format(RestDateTimeFormat);
    }
    this.paramsPlainObj[key] = value;
    return this;
  }

  public AddParameterArray(
    key: string,
    values: (string | number | dayjs.Dayjs)[],
  ) {
    console.log(`May plz use method AddParameter directly`);
    if (!values || !values.length) return this;

    const tailVal = values.at(-1);
    if (tailVal) {
      this.AddParameter(key, tailVal);
    }
    return this;
  }

  public AddBody(body: PlainObj) {
    if (!body || !Reflect.ownKeys(body).length) return this;
    for (const key in body) {
      this.bodyPlainObj[key] = body[key];
    }

    return this;
  }

  public GetTResponseAsync<T>() {
    return this.restCore.GetTResponse<T>(
      this.url,
      this.axiosConfHeaders,
      this.bodyPlainObj,
      this.paramsPlainObj,
    );
  }
}

RestException.ts

抽象类 RestCoreAbs 大致定义:

_RestCoreAbs.ts

基于 Axios 的请求封装方案

https://blog.ninoh.cc/loc-blog/8_axios-api-encapsulation[Copy]
本文作者
ninohx96
创建/发布于
Published On
更新/发布于
Updated On
许可协议
CC BY-NC-SA 4.0

转载或引用本文时请遵守“署名-非商业性使用-相同方式共享 4.0 国际”许可协议,注明出处、不得用于商业用途!分发衍生作品时必须采用相同的许可协议。