封装一个请求

145 阅读3分钟

如下,请求可以分为三部分
image.png

1.index.js中封装各类的请求,如get,post,put,delete,upload,login,logout,refresh等等请求。 2.request.js是创建一个axios赋予基础参数,并且添加响应拦截器。
3.requestUrl.js是用来抽取一个基础的url参数,并且做一个拼接。

下面按照这三个文件的引用顺序做一个单个文件的代码拆分分析

requestUrl.js

/**
 * 请求地址统一处理/组装
 * @param {*} actionName action方法名称
 */
export default function(actionName) {
    let url = process.env.VUE_APP_BASE_URL || "http://***.com"
    
    return url + actionName
}

request.js

/* jshint esversion: 6  */
import axios from "axios";
import Vue from "vue";
import router from "../router/index";
import store from "../store";
import requestUrl from "./requestUrl";

// 创建axios实例
const request = axios.create({
	timeout: 10000 * 10,
});

// response拦截器
request.interceptors.response.use(
	(response) => {
		// 101 用户名或密码错误
		// 102 REFRESH-TOKEN不存在/失效
		// 103 token验证失败
		// 104 未登录

		let code = response.data.code;
		if(code == 102 || (!store.state.refreshing && code == 104)){
			// 退出登陆
			store.commit("logout");
			router.replace({ name: "login" });
		}
		if (!store.state.refreshing && code == 103) {
			// token失效 刷新token
			Vue.prototype.ajax.refresh();
			response.data.msg = "长时间页面未更新,尝试重新提交或刷新页面";
		}
		return response.data;
	},
	(error) => {
		return Promise.reject(error);
	}
);
export { request, requestUrl };

index.js

1.里面需要引入的模块如下

import { request, requestUrl } from "./request";
import store from "../store/index";
import Vue from "vue";
import qs from "qs";

2.需要一个公共axios请求方法

/**
 * axios请求封装
 * @param {*} opt
 */
function send(opt, resolve, reject, success, error, complete) {
	// 获取refresh_token时,延迟请求
	if (store.state.refreshing) {
		setTimeout(() => {
			send(opt, resolve, reject, success, error, complete);
		}, 300);
		return;
	}
	let nowtime = new Date().getTime() / 1000;
        //overtime是登录成功之后端返回的时间加上登录的时间戳
	let overtime = Number(store.state.overtime);
	
	// 如果登陆时间大于8小时则直接退出
	if (store.state.token && overtime && nowtime - overtime > 8 * 3600) {
		store.commit("logout");
		router.replace({ name: "login" });
		return;
	}
	// 如果登陆时间小于8小时并且超出refreshtoken时间,则刷新token
	if (store.state.token && overtime && overtime < nowtime) {
		store.commit("changeRefresh", false);//改变store.state.refreshComplate
		ajax.refresh(opt, resolve, reject, success, error, complete);
		return;
	}
	if (store.state.refreshComplate) {
		let token = store.state.token;
		if (token) {
			opt.headers.token = token;
		}
	}
	request(opt)
		.then((res) => {
			resolve(res);
			if (success) success(res);
		})
		.catch((err) => {
			reject(err);
			if (error) error();
			Vue.prototype.$message.error("网络错误,请稍后重试");
		})
		.finally(() => {
			if (complete) complete();
		});
}

3.需要封装一个拿取token的方法

function getToken() {
	let token = store.state.token;
	if (!token) {
		store.commit("logout");
		Vue.prototype.$message.error("登陆信息失效,请重新登陆");
		router.replace({ name: "login" });
	}
	return token;
}

4.定义一个ajax对象在里面封装各种类型的方法,并且导出它

const ajax = {
    get(){},
    post(){},
    put(){},
    delete(){},
    upload(){},
    login(){},
    logout(){},
    refresh(){},
};
export { ajax };

get方法的封装

const ajax = {
	get: (url, params) => {
		let token = getToken();
		if (!token) return;
		let opt = {
			url: requestUrl(url),
			method: "get",
			headers: {
				"Content-Type": "application/x-www-form-urlencoded",
				token,
			},
			params,
		};
		return new Promise((resolve, reject) => {
			send(opt, resolve, reject);
		});
	}
}

post方法的封装

const ajax = {
        post: (url, params) => {
		let token = getToken();
		if (!token) return;
		let opt = {
			url: requestUrl(url),
			method: "post",
			headers: {
				"Content-Type": "application/x-www-form-urlencoded",
				token,
			},
			data: qs.stringify(params),
		};
		return new Promise((resolve, reject) => {
			send(opt, resolve, reject);
		});
	},
}

put方法的封装

const ajax = {
        put: (url, params) => {
		let token = getToken();
		if (!token) return;
		let opt = {
			url: requestUrl(url),
			method: "put",
			headers: {
				"Content-Type": "application/x-www-form-urlencoded",
				token,
			},
			data: qs.stringify(params),
		};
		return new Promise((resolve, reject) => {
			send(opt, resolve, reject);
		});
	},
}

delete方法的封装

const ajax = {
        delete: (url, params) => {
		let token = getToken();
		if (!token) return;
		let opt = {
			url: requestUrl(url),
			method: "delete",
			headers: {
				"Content-Type": "application/x-www-form-urlencoded",
				token,
			},
			params,
		};
		return new Promise((resolve, reject) => {
			send(opt, resolve, reject);
		});
	},
}

upload方法的封装

const ajax = {
        upload: (url, params) => {
		let token = getToken();
		if (!token) return;
		let opt = {
			url: requestUrl(url),
			method: "post",
			headers: {
				"Content-Type": "multipart/form-data",
				token,
			},
			data: toFormData(params),
		};
		return new Promise((resolve, reject) => {
			send(opt, resolve, reject);
		});
	},
}

login方法的封装

const ajax = {
        login: (params) => {
		store.commit("isRefresh", false);
		let opt = {
			url: requestUrl("/login"),
			method: "post",
			headers: {
				"Content-Type": "application/x-www-form-urlencoded",
			},
			data: qs.stringify(params),
		};
		return new Promise((resolve, reject) => {
			send(opt, resolve, reject);
		});
	},
}

logout方法的封装

const ajax = {
        logout: () => {
		store.commit("isRefresh", false);
		let token = getToken();
		if (!token) return;
		let opt = {
			url: requestUrl("/logout"),
			method: "post",
			headers: {
				"Content-Type": "application/x-www-form-urlencoded",
				token,
			},
		};
		return new Promise((resolve, reject) => {
			send(opt, resolve, reject, false, false, () => {
				store.commit("logout");
			});
		});
	},
}

refresh方法的封装

const ajax = {
        refresh: (...success) => {
		if (store.state.refreshing) return;
		store.commit("isRefresh", true);

		let opt = {
			url: requestUrl("/refresh_token"),
			method: "post",
			headers: {
				"Content-Type": "application/x-www-form-urlencoded",
				"refresh-token": store.state.refresh_token,
			},
		};
		return new Promise((resolve, reject) => {
			request(opt)
				.then((res) => {
					resolve(res);
					if (res.code == 0) {
						store.commit("setUserInfo", res.data);
						if (success) {
							if (success[0].headers && success[0].headers.token) {
								success[0].headers.token = res.data.token;
							}
							send(...success);
						}
					}else{
						ajax.logout()
					}
				})
				.catch((err) => {
					reject();
					Vue.prototype.$message.error("网络错误,请稍后重试");
				})
				.finally(() => {
					store.commit("isRefresh", false);
				});
		});
	},
}