封装Axios
- 1- 先安装Axios
- npm i axios -S
- 2- 引入Axios
- import axios from 'axios
- 3- 创建实例,自定义配置一个axios实例
- 4- 请求拦截器 给每个请求都设置请求头
- 5- 响应拦截器 发送请求后,后台会返回状态码,在响应拦截器中根据不同的状态码,做不同的操作
- 6- export default instance
import axios from 'axios'
import { Dialog, Toast } from 'vant'
const instance = axios.create({
baseURL: process.env.VUE_APP_BASE_URL, // 表示请求的接口地址的公共部分
timeout: 10000, // 请求超时
})
axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'
instance.interceptors.request.use((config) => {
const token = localStorage.getItem(token) // 存的token
config.headers['Authorization'] = `Bearer ${token}`
return config
}),
(error) => {
return Promise.reject(error)
}
instance.interceptors.response.use((response) => {
// 2xx 范围内的状态码都会触发该函数
// 如果状态码是200,返回data
if (response.status === 200) {
return response.data
} else {
// 如果状态码不是200,表示请求失败,可以弹出一条提示框提示错误信息
Toast.fail('请求出错,状态码为' + response.status)
}
return response
}),
(error) => {
// 超出 2xx 范围的状态码都会触发该函数
if (error.response) {
switch (error.response.status) {
case 401: {
Dialog.confirm({
title: '系统提示',
message: '登录状态已过期,您可以继续留在该页面,或者重新登录',
'confirm-button-text': '重新登录',
'cancel-button-text': '取消',
})
.then(() => {
// 清除token,跳转登录页
this.$router.replace('/login')
})
.catch(() => {
// 关闭
})
break
}
case 403: {
Dialog.alert({
title: '系统提示',
message: '拒绝访问',
})
break
}
case 404: {
Dialog.alert({
title: '系统提示',
message: '很抱歉,资源未找到',
})
break
}
case 500: {
Dialog.alert({
title: '系统提示',
message: '令牌校验失败,请重新登录',
}).then(() => {
// 清除token,跳转登录页
this.$router.replace('/login')
})
break
}
case 504: {
Dialog.alert({
title: '系统提示',
message: '网络超时',
})
break
}
default: {
Toast.fail('请求出错,状态码为' + response.status)
break
}
}
}
return Promise.reject(error)
}
export default instance
又更新了
import axios from "axios";
import type { AxiosInstance, AxiosRequestConfig, AxiosResponse } from "axios";
import { ElMessage, ElMessageBox } from "element-plus";
// 创建axios实例
const service: AxiosInstance = axios.create({
// baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
// 但是由于使用的qiankun,后端有多个微服务,无法统一,就不写在这里,而是vue.config.js的proxy里面,根据不同的服务名设置不同的服务器ip
timeout: 60000, // request timeout
headers: {
"Content-Type": "application/json",
},
});
// 请求拦截
service.interceptors.request.use(
(config) => {
// 主应用
const token = localStorage.getItem('token')
config.headers.common["Authorization"] = token;
// 子应用:给每个post请求中加上用户信息, 模拟header中加token(由于后端解析token困难)
if (config.method === "post") {
config.data = config.data ? config.data : {};
if (localStorage.getItem("userInfo")) {
let { userId, userName } = JSON.parse(
localStorage.getItem("userInfo")!
);
config.data.createBy = userId;
config.data.createName = userName;
}
}
return config;
},
(error) => {
return Promise.reject(error);
}
);
// 响应拦截
service.interceptors.response.use(
(response: AxiosResponse) => {
// 接口不规范, 返回多种, 统一做个兼容
const { status, msg, code, message } = response.data;
const statusCode = status || code;
if (statusCode !== 200) {
ElMessage({
message: msg || message || "Error",
type: "error",
duration: 5 * 1000,
});
if (statusCode === 406) { // login接口总是返回406,为了拿到第三方登录页的地址
return response.data;
}else if(statusCode === 407 || statusCode === 410) { // 未携带token或token失效
ELMessage.error("登录已失效,请重新登录!");
logout().then((res)=>{
if(res.code === 200){
// 退出登录是需要清空浏览器缓存和本地缓存内的东西的
sessionStorage.clear()
localStorage.removeItem("userInfo")
localStorage.removeItem("token")
// 回到登录页
...
}
}).catch((err)=>{})
}
return Promise.reject(new Error(msg || "Error"));
} else {
return response.data;
}
},
(error) => {
ElMessage({
message: error.message,
type: "error",
duration: 5 * 1000,
});
return Promise.reject(error);
}
);
export default service;