如何封裝網絡請求框架
年末的時候用了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