@itshixun/qst-request-lib
TypeScript icon, indicating that this package has built-in type declarations

1.1.11 • Public • Published

@itshixun/qst-request-lib

QST接口请求工具库

1. 常用类型和枚举定义:

  • QstResult: 约定的数据响应类型
    /** 约定的常规接口返回数据结构体 */
    export interface QstResult<T> {
      /** http状态码 3位数 比如200、401、500等 */
      status: number;
      /** 扩展状态码 7位数 比如2000000 4010000 4000297 5000000等 */
      code: number;
      /** 成功标识 */
      success?: boolean;
      /** 消息 */
      message?: string;
      /** 返回的数据 */
      data?: T;
      /** 额外的返回数据,比如用户中心的extras.failureCount,返回登录错误的次数 */
      extras?: Record<string, unknown>;
    }
  • QstPagination: 约定的分页数据类型
    /** 约定的分页数据结构 */
    export interface QstPagination<T> {
      /** 总条数 */
      total: number;
      offset: number;
      limit: number;
      /** 当前页码 */
      pageNumber: number;
      /** 每夜条数 */
      pageSize: number;
      /** 数据数组 */
      rows: T[];
    }
  • ContentTypeEnum: ContentType类型枚举
    /** request contentType */
    export enum ContentTypeEnum {
      /** json */
      JSON = 'application/json;charset=UTF-8',
      /** form-data qs */
      FORM_URLENCODED = 'application/x-www-form-urlencoded;charset=UTF-8',
      /** form-data upload */
      FORM_DATA = 'multipart/form-data;charset=UTF-8',
    }

2. aioxs请求封装方法:requestWrapper

封装常规axios请求方法:requestWrapper:提炼通用的响应处理和错误提示,剥离AxiosResponse<T>封装并返回T类型的数据,业务端通常不需要再进行Promise.catch,仅需要处理必要的响应结果,除非在处理响应结果时有可能抛出业务逻辑相关错误时,再通过Promise.catch进行处理。

2.1 选项设置

在使用requestWrapper方法前,首先要进行选项设置。请求封装方法的选项类型RequestWrapperOption定义如下:

/** 请求封装方法的选项类型定义 */
export interface RequestWrapperOption<T = any> {
  /**
   * 自定义错误处理方法,仅在需要特殊处理的接口请求时使用此方法,作为requestWrapper中默认错误处理方法的补充
   * 要求保持返回的错误类型仍为AxiosError,保证错误信息在Promise链中的延续和可追溯
   */
  resolveError?: (err: AxiosError<T>) => AxiosError<T>;
  /** 显示错误消息提示的方法 */
  handleMessage?: (msg: string, err?: AxiosError<T>) => void;
  /** 错误已处理标志位,默认AxiosError.code === 'handled'时,表示该错误已处理,后续错误处理中判断code==='handled'时,不再弹窗错误提示,避免重复弹出 */
  handledCode?: string;
  /** 处理401(需要登录)的方法 */
  handle401?: (err: AxiosError<T>) => void;
  /** 处理403(无权限需要登录)的方法 */
  handle403?: (err: AxiosError<T>) => void;
  /** aixos实例,使用qstRequest的get/post等便捷请求别名时,需要传入该实例,否者默认使用aixos静态实例 */
  axiosInstance?: AxiosInstance;
}

我们可以通过setDefaultRequestWrapperOption设置requestWrapper方法的全局默认选项,比如:

setDefaultRequestWrapperOption({
  /** 使用element-plus的Message组件弹出错误提示消息 */
  handleMessage: (msg: string) => ElMessage.error(msg),
  /** 默认error.code 为 handled 时,表示错误已处理,不需要再弹出提示 */
  handledCode: 'handled',
  /** 401时跳转到登录页 */
  handle401: () => router.replace({ name: 'login' }),
  /** 403时无权限,跳转到登录页 */
  handle403: () => {
    ElMessage.error('当前登录角色无权限,请重新登录');
    logout();
    router.replace({ name: 'login' });
  },
  /** 常规的请求错误在requestWrapper中已做处理,一般不需要此处自定义resolveError方法,这里可以不做设置 */
  resolveError: (err: AxiosError<unknown>) => err,
  /** 设置qstRequest使用的默认axios实例 */
  axiosInstance: mainInstance,
});

2.2 调用方法

一个常规的axios请求流程,大致如下:

/** axios请求示例 */
axios
  .get<QstResult<ResData>>('/api/xxx')
  .then((res: AxiosResponse<QstResult<ResData>>) => {
    // 处理返回数据,取得res.data.data
    const data = getResult(res);
    return data;
  })
  .catch((err: AxiosError<QstResult<ResData>>) => {
    // 处理错误信息,弹出错误消息
    handleError(err);
    return Promise.reject(err);
  });

我们通过requestWrapper方法,提炼通用的响应处理和错误提示,剥离AxiosResponse<T>封装并返回T类型的数据,业务端通常不需要再进行Promise.catch,仅需要处理必要的响应结果,除非在处理响应结果时有可能抛出业务逻辑相关错误时,才通过Promise.catch进行处理。上面的方法,使用requestWrapper方法的示例如下:

/** 使用requestWrapper封装请求,此处使用默认设置,不再传入RequestWrapperOption选项 */
requestWrapper<QstResult<ResData>>(() => axios.get('/api/xxx')).then((res: QstResult<ResData>) => {
  return res.data;
});

上面的例子,经过requestWrapper处理后,Promise.then可以直接取得剥离AxiosResponse封装的响应数据。同时所有的常见请求错误,都已经在requestWrapper内部做了处理,如果确定Promise.then中不会抛出业务相关的错误,就不需要再使用Promise.catch进行错误处理了。

针对具体的接口,我们也可以传入专门针对该接口的RequestWrapperOption选项,从而使不同的接口可以获得各自不同的处理方式。比如在请求登录接口时,如果返回401说明登录接口本身的后端逻辑出错了,我们给出一个服务端错误的提示;另外我们希望登录接口使用原生alert的方式提醒用户。我们可以像下面这样,调用requestWrapper方法时传入RequestWrapperOption选项:

requestWrapper<QstResult<ResData>>(
  () => axios.post('/api/login', { loginData }),
  // 传入RequestWrapperOption,会通过Object.assign合并默认的RequestWrapperOption
  {
    handle401: () => alert('服务端错误:登录接口返回401!'),
    handleMessage: (msg: string) => alert(msg),
  }
).then((res) => {
  // 保存登录token
  setToken(res.data.accessToken);
  // 登录成功的后续处理...
});

通过setDefaultRequestWrapperOption设置全局选项,并且具体接口也可以在调用requestWrapper时传入不同的配置选项,可以实现:大部分接口请求使用统一的错误处理/错误提醒/401登录跳转等方法的同时,部分特殊接口使用自定义的错误处理/错误提醒/401状态处理方法。

3 仿aixos的请求别名

基于requestWrapper方法,我们构建了qstRequest对象,进一步封装了请求别名(get/post等)方法。我们可以像使用axios的便捷请求别名方法一样,以更简洁和符合使用习惯的方式进行接口请求。比如上面2.2 调用方法的示例:

/** 使用requestWrapper封装请求,此处使用默认设置,不传入RequestWrapperOption选项 */
requestWrapper<QstResult<ResData>>(() => axios.get('/api/xxx'));

我们也可以使用便捷请求别名进行请求,如下所示:

/** 使用qstRequest.get请求别名,此处使用默认设置,不传入RequestWrapperOption选项 */
qstRequest.get<QstResult<ResData>>('/api/xxx');

上述示例使用全局设置的默认RequestWrapperOption选项。如果某个特定接口使用另外的aixos实例进行请求,我们可以如下例这样,传入RequestWrapperOption选项,针对具体请求进行特殊配置:

qstRequest.post<QstResult>('/api/xxx/save', data, config, {
  // 针对本接口,使用名为"mySaveInstance"的axios实例进行请求
  axiosInstance: mySaveInstance,
  // 配置本接口不弹出错误提示消息,仅在控制台打印错误信息
  handleMessage: (msg: string) => {
    console.error(msg);
  },
});

注意:axios中AxiosInstance的定义,在v1.5.x和1.6.x中不同,因此如果您使用typescript开发,在配置RequestWrapperOption的axiosInstance时,需要安装最新的axios版本(目前 1.6.1),才可保证ts类型正确。

qstRequest的请求方式别名列表

qstRequest: {
  get<T = any, D = any>(url: string, config?: AxiosRequestConfig<D>, option?: RequestWrapperOption<T>): Promise<T>;
  delete<T = any, D = any>(url: string, config?: AxiosRequestConfig<D>, option?: RequestWrapperOption<T>): Promise<T>;
  post<T = any, D = any>(url: string, data?: D, config?: AxiosRequestConfig, option?: RequestWrapperOption<T>): Promise<T>;
  put<T = any, D = any>(url: string, data?: D, config?: AxiosRequestConfig, option?: RequestWrapperOption<T>): Promise<T>;
  patch<T = any, D = any>(url: string, data?: D, config?: AxiosRequestConfig, option?: RequestWrapperOption<T>): Promise<T>;
  postForm<T = any, D = any>(url: string, data?: D, config?: AxiosRequestConfig, option?: RequestWrapperOption<T>): Promise<T>;
  putForm<T = any, D = any>(url: string, data?: D, config?: AxiosRequestConfig, option?: RequestWrapperOption<T>): Promise<T>;
  patchForm<T = any, D = any>(url: string, data?: D, config?: AxiosRequestConfig, option?: RequestWrapperOption<T>): Promise<T>;
}

4 取得Axios原始响应数据AxiosResponse

上述工具(requestWrapper和qstRequest)帮助我们剥离AxiosResponse结构,直接返回T类型的数据,方便进行后续的数据处理;但是有些特殊情况下需要获取完整的AxiosResponse数据,比如要获取 response headers 中某个字段的值。这里我们通过requestWrapperRaw的方法,或者qstRequestRaw对象的get/post等请求别名,来获取Axios的原始响应数据:

/** 使用requestWrapperRaw封装请求,返回原始的Axios响应数据,即AxiosResponse<ResponseData>类型的数据 */
requestWrapperRaw<ResponseData>(() => axios.get('/api/xxx'));

/** 同样,使用qstRequestRaw下定义的请求方法别名,返回原始Axios响应数据 */
qstRequestRaw.get<ResponseData>('/api/xxx');

Readme

Keywords

none

Package Sidebar

Install

npm i @itshixun/qst-request-lib

Weekly Downloads

2

Version

1.1.11

License

MIT

Unpacked Size

151 kB

Total Files

12

Last publish

Collaborators

  • lijunran
  • mutueye
  • guoyingxu
  • donkeyliuyan