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