在项目下新建services文件夹,包含三个文件(methods.ts,request.ts,url.ts)
methods.ts 接口方法封装文件
request.ts axios二次封装,增加拦截器等,不一定要使用axios 可以封装任意请求框架,此处以axios,fetch示例
url.ts 请求地址
1、url.ts 请求地址
2、request.ts 二次封装 返回报错可以一起封装在这个文件,具体看项目要求
(1)axios
首先设置基础设置
建立类Request
import axios, {AxiosInstance, AxiosResponse} from "axios";
import url from "@/services/url";
axios.defaults.timeout = 60000 ; // 设置全局请求超时时间
axios.defaults.baseURL = url.baseUrl // 设置全局请求基地址
export default class Request {
private spinningAxios = axios.create(); // 建立请求时会产生全局Loading的axios实例
private noSpinningAxios = axios.create(); // 建立请求时不会产生全局Loading的axios实例
constructor() {
this.addInterceptors(this.spinningAxios,true);
this.addInterceptors(this.noSpinningAxios,false);
}
private addInterceptors(requestMain: AxiosInstance, loading: boolean): void {
requestMain.interceptors.request.use(options => {
// 对全局请求的options进行更改,例如增加动态头部信息等
if(loading)
{
// 自定义全局Loading的产生方式,在项目开发中建议在全局写一个工具类 例如 xxxx.showLoading()
}
return options;
},error => {
// 错误捕捉 此时的错误为最外层status的错误
return Request.outError(error,loading)
})
requestMain.interceptors.response.use(response => {
// 处理全局请求的返回response,例如对返回值进行判断
return Request.disposeResponse(response,loading)
},error => {
// 错误捕捉 此时的错误为最外层status的错误
return Request.outError(error,loading)
})
}
private static outError(error: any, loading: boolean): Promise<string> {
if(loading)
{
// 自定义全局Loading的关闭方式,在项目开发中建议在全局写一个工具类 例如 xxxx.hideLoading()
}
const { response = {} } = error;
return Promise.reject(response.statusText || (error && error.toString()) || "未知错误");
}
private static disposeResponse(response: AxiosResponse, loading: boolean): AxiosResponse | Promise<any> {
if(loading)
{
// 自定义全局Loading的关闭方式,在项目开发中建议在全局写一个工具类 例如 xxxx.hideLoading()
}
// 对接口返回的数据进行判断,例如接口中 code 的值 200为成功,500为失败,401为未登录时进行各个操作,此处可以使用枚举
const { data } = response;
switch (data.code) {
// case insideStatus.success: // 200
// return response;
// case insideStatus.error: // 500
// return Promise.reject(data.msg);
// case insideStatus.noLogin: // 401
// this.utils.toLogin();
// return Promise.reject(data.msg);
// default:
// return Promise.reject(data.msg);
default: return response; //示例数据,请自行剔除
}
}
public async post<T,S>(url: string, data: T): Promise<S | string> {
return this.spinningAxios.post(url,data,{
// 添加例如 headers 之类的属性
}).then(res => Promise.resolve(res.data)).catch(err => Promise.reject(err.toString()))
}
public async get<T,S>(url: string, data: T): Promise<S | string> {
return this.spinningAxios.get(url,{
params: data,
// 添加例如 headers 之类的属性
}).then(res => Promise.resolve(res.data)).catch(err => Promise.reject(err.toString()))
}
public async postNoLoading<T,S>(url: string, data: T): Promise<S | string> {
return this.noSpinningAxios.post(url,data,{
// 添加例如 headers 之类的属性
}).then(res => Promise.resolve(res.data)).catch(err => Promise.reject(err.toString()))
}
public async getNoLoading<T,S>(url: string, data: T): Promise<S | string> {
return this.noSpinningAxios.get(url,{
params: data,
// 添加例如 headers 之类的属性
}).then(res => Promise.resolve(res.data)).catch(err => Promise.reject(err.toString()))
}
}
(2)fetch
import url from "./url";
export default class Request {
private async getValue<T>(
method: "POST" | "GET",
fetchPath: string,
data: T,
loading: boolean
): Promise<any> {
if(loading)
{
// 自定义全局Loading的产生方式,在项目开发中建议在全局写一个工具类 例如 xxxx.showLoading()
}
// 如果是get请求,请将数据封装拼接在url的后面 post请求请放入参数中的body
return fetch(`${url.baseUrl}${fetchPath}`, {
method,
headers: {
// 自定义头部信息
accept: "*",
"content-type": "application/json",
},
// post数据参照之下的写法
body: data && JSON.stringify(data)
})
.then(async res => {
const data = await res.json();
switch (data.code) {
// case insideStatus.success: // 200
// return data;
// case insideStatus.error: // 500
// return Promise.reject(data.msg);
// case insideStatus.noLogin: // 401
// this.utils.toLogin();
// return Promise.reject(data.msg);
// default:
// return Promise.reject(data.msg);
default: return data; //示例数据,请自行剔除
}
})
.catch(err => {
const tempErr = err.toString();
return Promise.reject(tempErr);
})
.finally(() => {
if(loading)
{
// 自定义全局Loading的关闭方式,在项目开发中建议在全局写一个工具类 例如 xxxx.hideLoading()
}
});
}
public async post<T,S>(fetchPath: string, data: T): Promise<S | string> {
return this.getValue("POST", fetchPath, data, true)
.then(res => Promise.resolve(res))
.catch(err => Promise.reject(err));
}
public async postNoLoading<T,S>(fetchPath: string, data: T): Promise<S | string> {
return this.getValue("POST", fetchPath, data, false)
.then(res => Promise.resolve(res))
.catch(err => Promise.reject(err));
}
public async get<T,S>(fetchPath: string, data: T): Promise<S | string> {
return this.getValue("GET", fetchPath, data, true)
.then(res => Promise.resolve(res))
.catch(err => Promise.reject(err));
}
public async getNoLoading<T,S>(fetchPath: string, data: T): Promise<S | string> {
return this.getValue("GET", fetchPath, data, false)
.then(res => Promise.resolve(res))
.catch(err => Promise.reject(err));
}
}
不管是axios还是fetch 在最后post,get,postNoLoading,getNoLoading时都可以将Promise.reject(err)替换成一个公用方法,例如在公用方法showError全局通知错误等,最后在公用方法返回Promise.reject(err)即可
3、methods.ts 请求方法封装
此处有两种封装方法,一种返回Callback,一种返回Promise,看个人喜好或项目要求自行选择
返回Promise
返回Callback
调用接口(普通示例,React,Vue均可用,Vue2.x版本建议挂载到原型链上进行使用,Vue3.x版本建议以下方式使用,请注意,这里指的版本不是vue-cli的版本,而是vue的版本)
返回Promise示例
const http = new Methods();
http
.login<Login, any>({
userPhone: "123456789",
userPassword: "123456789"
})
.then(res => {
//成功回调
console.log(res);
})
.catch(err => {
//失败回调
console.log(err);
});
返回Callback示例
const http = new Methods();
http.login<Login, any>(
{
userPhone: "123123123",
userPassword: "123456"
},
res => {
//成功回调
console.log(res);
},
err => {
//失败回调
console.log(err);
}
);
返回结果
如果您觉得此博客有错误或改进之处,请留言