1.axios的封装请求
javascript
复制代码
import axios from "axios";
import { apiUrl } from "@/config/global-config.js";
import { useUserStore } from "../stores";
import { usePageRoute } from "@/composable/usePageRoute.js";
// 创建 axios 实例
const instance = axios.create({
baseURL: apiUrl,
timeout: 60000,
headers: { "Content-Type": "application/json" },
});
// 刷新token的方法
const refreshToken = async () => {
const userStore = useUserStore();
try {
const response = await instance.post(
"/auth/refresh",
{},
{
headers: { Authorization: `Bearer ${userStore.token}` },
}
);
if (response.data.code === 200) {
userStore.setToken(response.data.data.token);
return true;
}
return false;
} catch (error) {
return false;
}
};
let isRefreshing = false; // 是否正在刷新token
let refreshSubscribers = []; // 存储等待的请求
// 通知所有等待的请求
const onRefreshed = (token) => {
refreshSubscribers.forEach((callback) => callback(token));
refreshSubscribers = [];
};
// 添加请求到等待队列
const addSubscriber = (callback) => {
refreshSubscribers.push(callback);
};
// 请求拦截器
instance.interceptors.request.use(
(config) => {
const userStore = useUserStore();
const token = userStore.token;
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
},
(error) => Promise.reject(error)
);
// 响应拦截器
instance.interceptors.response.use(
(response) => response.data,
async (error) => {
const { config, response } = error;
const userStore = useUserStore();
if (response && response.status === 401) {
// 如果刷新token请求失败,直接登出
if (config.url.includes("/auth/refresh")) {
await handleLogout();
return Promise.reject(new Error("登录已失效"));
}
// 如果没有正在刷新token,开始刷新
if (!isRefreshing) {
isRefreshing = true;
try {
const refreshResult = await refreshToken();
if (refreshResult) {
const newToken = userStore.token;
onRefreshed(newToken);
config.headers.Authorization = `Bearer ${newToken}`;
return instance(config);
} else {
await handleLogout();
return Promise.reject(new Error("登录已失效"));
}
} finally {
isRefreshing = false;
}
}
// 返回一个Promise,将请求加入等待队列
return new Promise((resolve) => {
addSubscriber((token) => {
config.headers.Authorization = `Bearer ${token}`;
resolve(instance(config));
});
});
}
console.error("请求错误:", response.data.msg || "请求错误");
return Promise.reject(error);
}
);
// 处理登出
const handleLogout = async () => {
const userStore = useUserStore();
const pageRoute = usePageRoute();
const fullPagePath = pageRoute.getCurrentFullPagePath();
localStorage.setItem("fullPage", fullPagePath);
alert("登录已失效,请重新登录");
userStore.clearToken();
userStore.clearUser();
setTimeout(() => {
window.location.href = "/pages/login/login";
}, 2000);
};
// 导出GET请求方法
export const $get = (url, params, options = {}) => {
return instance.get(url, { params, ...options });
};
// 导出POST请求方法
export const $post = (url, data, options = {}) => {
return instance.post(url, data, ...options);
};
2.fetch的封装请求
javascript
复制代码
import { apiUrl } from "@/config/global-config.js";
import { useUserStore } from "../stores";
import { usePageRoute } from "@/composable/usePageRoute.js";
// 刷新token的方法
const refreshToken = async () => {
const userStore = useUserStore();
try {
const response = await fetch(`${apiUrl}/auth/refresh`, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${userStore.token}`,
},
});
const data = await response.json();
if (data.code === 200) {
userStore.setToken(data.data.token);
return true;
}
return false;
} catch (error) {
return false;
}
};
let isRefreshing = false; // 是否正在刷新token
let refreshSubscribers = []; // 存储等待的请求
// 通知所有等待的请求
const onRefreshed = (token) => {
refreshSubscribers.forEach((callback) => callback(token));
refreshSubscribers = [];
};
// 添加请求到等待队列
const addSubscriber = (callback) => {
refreshSubscribers.push(callback);
};
// 处理登出
const handleLogout = async () => {
const userStore = useUserStore();
const pageRoute = usePageRoute();
const fullPagePath = pageRoute.getCurrentFullPagePath();
localStorage.setItem("fullPage", fullPagePath);
alert("登录已失效,请重新登录");
userStore.clearToken();
userStore.clearUser();
setTimeout(() => {
window.location.href = "/pages/login/login";
}, 2000);
};
// 封装fetch请求
const fetchWithAuth = async (url, options = {}) => {
const userStore = useUserStore();
const token = userStore.token;
const headers = {
"Content-Type": "application/json",
...options.headers,
};
if (token) {
headers.Authorization = `Bearer ${token}`;
}
try {
const response = await fetch(`${apiUrl}${url}`, {
...options,
headers,
});
if (response.status === 401) {
if (!isRefreshing) {
isRefreshing = true;
try {
const refreshResult = await refreshToken();
if (refreshResult) {
const newToken = userStore.token;
onRefreshed(newToken);
return fetchWithAuth(url, options);
} else {
await handleLogout();
throw new Error("登录已失效");
}
} finally {
isRefreshing = false;
}
}
return new Promise((resolve) => {
addSubscriber((token) => {
options.headers.Authorization = `Bearer ${token}`;
resolve(fetchWithAuth(url, options));
});
});
}
return response.json();
} catch (error) {
console.error("请求错误:", error.message || "请求错误");
throw error;
}
};
// 导出GET请求方法
export const $get = (url, params, options = {}) => {
const queryString = new URLSearchParams(params).toString();
return fetchWithAuth(`${url}?${queryString}`, { ...options, method: "GET" });
};
// 导出POST请求方法
export const $post = (url, data, options = {}) => {
return fetchWithAuth(url, {
...options,
method: "POST",
body: JSON.stringify(data),
});
};