切换页面取消上个页面请求
背景
你有没有碰上过请求超级慢的情况,然后切换完页面后,请求还在继续,搞得整个服务器卡的不行。。。
so
为了减轻服务器的负担,我们做一个优化处理:切换页面后取消上个页面的请求 ✌️
大体思路
页面初始加载前,也就是router.beforeEach中,通过axios的AbortController取消上个页面请求
干货 - 直接上核心代码(此处用vue3举例说明)
store
import { reactive } from 'vue';
import { defineStore } from 'pinia';
type pageDataType = {
controllers?: any;
};
// page store
export const usePage = defineStore('page', () => {
const pageData = reactive<pageDataType>({
controllers: {}, // 用于取消请求的控制器
});
/**
* 更新请求数据
* @param newData { pageDataType }
*/
const updatePageData = (newData: pageDataType) => {
if (newData.controllers) pageData.controllers = newData.controllers;
};
return { pageData, updatePageData };
});
axios请求
拦截器
...
import axios from 'axios';
import { usePage } from '@/stores/page';
import type {
AxiosRequestConfig,
} from 'axios';
type AxiosRequestType = AxiosRequestConfig & {
switchPageNotCancelRequest?: boolean; // 切换页面不取消请求
};
axios.interceptors.request.use((config: AxiosRequestType) => {
const { pageData, updatePageData } = usePage();
const { controllers } = pageData;
// 添加控制器,用于切换页面取消请求
const controller = new AbortController();
config.signal = controller.signal;
if (!config.switchPageNotCancelRequest) {
const identity = (config.url || '') + Date.now() + Math.random();
controllers[identity] = controller;
updatePageData({ controllers });
}
return config;
});
...
api
axios.get('/messages', { switchPageNotCancelRequest: true })
路由
...
import { usePage } from '@/stores/page';
/**
* @description 取消跳转前页面的请求
*/
const abortAxios = () => {
// 路由改变 取消axios请求
const { pageData, updatePageData } = usePage();
const controllers = pageData.controllers;
for (const key in controllers) {
controllers[key].abort();
}
updatePageData({ controllers: {} });
};
router.beforeEach(async (to, from) => {
// 取消上个页面的请求
abortAxios();
});
...
需要解释吗?不需要就不用往下看了
- 全局状态管理,存储请求的controller
- axios拦截器中判断,如果没有switchPageNotCancelRequest参数,则在请求拦截中储存此请求的controller
- 在路由拦截前置守卫中,通过遍历store中的controllers,调用controller.abort()取消上个页面的全部请求
相关链接
完~