如何封装网络请求框架
年末的时候用了typescript做新项目,还是学到很多,记录一下,学了之后,先是学了下如何将Axios改成Typescript版本的,Typescript在我的理解是加了类型的限制,八月份面试的时候,有个人问我,ts和js有什么不同?
大概是强类型更加规范,对面向对象支持比较好.因为大学学的是JAVA搞过几年安卓,所以对面向对象的语言很有好感,到现在我还是觉得JAVA很规范,我是不是对不住web前端?我是真在安卓上学到很多.
当然对ts,到现在我也不能讲出一朵花,一直写业务,说实话,没时间去反思.个人还没什么深刻的理解,不过会带着这个问题去学习.
正题,不废话.
单例模式创建AXIOS实例
一般来说,基本地址是固定的,全局使用,就需要用单例,只让其分配一次,单例有懒饿汉,做前端很少涉及线程的,所以就不用考虑加锁保持变量只被一个线程访问之类,除非业务有需求,例如:支付业务平台和普通业务平台是分开的
static关键字不能少,static优先于对象存在,可通过类名直接访问,因为this指向是实例,所以这里不能用this访问,如果不加上static,则实例不是全局的,每一次请求都会生成,而设置为static类全局变量,随着类加载去产生,只会生成一次.私有化,只有类本身才能改变其值.
如何深入理解static关键字,研究js的内存管理之后去说
class NetWorkUtils {
private static instance: AxiosInstance | null = null;
constructor() {
if (NetWorkUtils.instance === null) {
NetWorkUtils.instance = axios.create({
baseURL: process.env.VUE_APP_URL,
timeout: 50000, // request timeout
});
}
//TODO
//可配置下请求拦截器
}
}
针对多个平台基地址不同,baseURL作为参数,导出对象供使用,仍然能保持全局唯一,去掉static关键字
export const NetWorkUtil = new NetWorkUtils(process.env.VUE_APP_URL);
export const NetWorkPayUtil = new NetWorkUtils(process.env.VUE_APP_PAY_URL);
响应父实体类
响应数据的格式往往统一,data里面的类型多种形态,用泛型代替,到时候反射为原类型
export default interface BaseResponse<T = any> {
code: string;
data: T;
msg: string;
}
声明类型准备上
declare type Methods =
| 'get'
| 'GET'
| 'delete'
| 'DELETE'
| 'head'
| 'HEAD'
| 'options'
| 'OPTIONS'
| 'post'
| 'POST'
| 'put'
| 'PUT'
| 'patch'
| 'PATCH';
规定返回类型为AxiosPromise
import axios, {
AxiosInstance,
AxiosPromise,
AxiosRequestConfig,
AxiosResponse,
} from 'axios';
axios.defaults.withCredentials = true;
//后端不支持RESTful接口,如果支持还可以使用Record定义每个方法,然后去实现
declare type Methods =
| 'get'
| 'GET'
| 'post'
| 'POST'
/**
* transformRequest 函数数组
*/
interface Config {
data?: any;
params?: any;
url?: string;
headers?: any;
responseType?: string;
transformRequest?: Array<any>;
}
class NetWorkUtils {
private instance: AxiosInstance | null = null;
constructor(url:string) {
if (this.instance === null) {
this.instance = axios.create({
baseURL: url,
timeout: 5000, // request timeout
});
this.initInterceptors();
}
}
/**
* 初始化请求响应的拦截器
*/
private initInterceptors(): void {
this.instance!.interceptors.request.use(
(config: AxiosRequestConfig) => {
const sid = window.localStorage.getItem('sessionId');
if (sid) {
Object.assign(config.headers, { sessionId: sid });
}
return config;
},
error => {
Promise.reject(error);
}
);
this.instance!.interceptors.response.use(
(response: AxiosResponse) => {
return response;
},
error => {
return error;
}
);
}
/**
* @param {string} url 请求连接
* @param {string} method HTTP方式
* @param {any} data 数据
* @returns {Promise} 返回的异步
*/
createAPI<T,R>(url: string, method: Methods, data?: T): AxiosPromise<R> {
const config: Config = {};
if (method === 'get' || method === 'GET') {
config.params = data;
} else {
config.data = data;
}
return this.instance!(Object.assign(config, { method, url }));
}
createFormAPI<T>(
url: string,
method: Methods,
data?: T,
responseType?: string
): AxiosPromise {
if (!responseType) {
responseType = 'json';
}
const config: Config = {
data: data,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
responseType,
transformRequest: [],
};
config.transformRequest = [
function(data: { [x: string]: string | number | boolean }) {
let ret = '';
for (const key in data) {
ret += `${encodeURIComponent(key)}=${encodeURIComponent(data[key])}&`;
}
return ret;
},
];
return this.instance!(Object.assign(config, { method, url }));
}
}
export const NetWorkUtil = new NetWorkUtils(process.env.VUE_APP_URL);
export const NetWorkPayUtil = new NetWorkUtils(process.env.VUE_APP_PAY_URL);
创建请求
export async function login(data: IUserParam): Promise<BaseResponse<IUser>> {
return (await NetWorkUtil.createAPI('/登录', 'GET', data))
.data;
}
以上均为我不成熟的代码.各位根据需求来
如果支持RESTful方法,可以利用Record改成如下方式
enum IHttpMethods {
GET = 'get',
POST = 'post',
DELETE = 'delete',
PUT = 'put',
}
const methods = ["get", "post", "delete", "put"];
interface IHttpFn {
<T = any>(url: string, config?: AxiosRequestConfig): Promise<T>
}
type IHttp = Record<IHttpMethods, IHttpFn>;
const httpMethods: IHttp = methods.reduce((map: any, method: string) => {
map[method] = (url: string, options: AxiosRequestConfig = {}) => {
const { data, ...config } = options;
return (axios as any)[method](url, data, config)
.then((res: AxiosResponse) => {
if (res.data.errCode) {
//todo somethins
} else {
//todo somethins
}
});
}
return map
}, {})
export default httpMethods;
————————————————
版权声明:本文为CSDN博主「问白」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_38080573/article/details/92838045