封装一个规范的请求通常涉及到以下几个方面:
- 请求方法(GET、POST 等)
- 请求参数构造(根据使用的请求库,包括不同 Method 要求的 params 格式、空值处理等)
- 格式转换(如请求体和返回体参数的下划线格式和驼峰格式转换,一般前端会用驼峰命名格式,后台会用下划线命名格式)
- 请求头构造(根据不同请求类型,比如 json、form、multipart)
- 返回体处理(包括成功和错误处理等)
下面是一个具体的实现:
src/app.ts
import { viewClient } from 'src/request/index';
const info = await viewClient.getUserInfo();
console.log(info);
src/request/index.ts
import UserClient from './UserClient';
export const viewClient = new ViewClient();
src/request/UserClient.ts
class UserClient extends ClientBase {constructor() {super('/center-api');}getUserInfo(params) {return this.get('/v1/user/getUserInfo', params);}updateUserInfo(params) {return this.post('/v1/user/updateUserInfo', params);}uploadData(params) {return this.post('/v1/user/uploadData', params, {dataType: 'multipart'})}downloadData(params) {return this.get('/v1/user/downloadData', params, {responseType: 'blob'})}
}
export default UserClient;
src/request/ClientBase.ts
import axios from 'axios';
import humps from 'humps';
import qs from 'qs';
import isPlainObject from 'lodash/isPlainObject';
import { ElMessage } from 'element-plus';interface IOption {underscoreRequestData: boolean; // 是否将入参对象的键从驼峰式命名转换为下划线分隔的形式camelizeResponseData: boolean; // 是否将返回体对象的键从下划线分割命名转换为驼峰式的形式removeEmptyValue: boolean; // 是否删除空入参removeEmptyValueTypeList: unknown[]; // value 值等于什么时被视为空入参 例如 [null, undefined, NaN, '']dataType: string; // request Content-TyperesponseType: string; // response Content-Type
}
type PartialIOption = Partial<IOption>;
type IOptionDefault = Pick<PartialIOption,'underscoreRequestData' | 'camelizeResponseData' | 'dataType'
>;
const DEFAULT_OPTIONS: IOptionDefault = {underscoreRequestData: true,camelizeResponseData: true,dataType: 'json',
};
export class ClientBase {// 不同实体 API 请求的前缀,如 UserClient 为 /center-apiapiUrlPrefix: string;// 请求的配置项options: PartialIOption;// 是否登录中isLogging: boolean;/*** constructor* @param apiURLPrefix* @param options*/constructor(apiUrlPrefix = '', options = {}) {this.apiUrlPrefix = apiUrlPrefix;this.options = {...DEFAULT_OPTIONS,...options,};this.isLogging = false;}/*** get, post, put, delete* @param url 请求api* @param data 入参* @param options 特定请求额外配置项* @returns*/get(url: string, data?: any, options?: any) {return this._request(url, 'get', data, options);}post(url: string, data?: any, options?: any