切换页面取消上个页面请求

968 阅读1分钟

切换页面取消上个页面请求

背景

你有没有碰上过请求超级慢的情况,然后切换完页面后,请求还在继续,搞得整个服务器卡的不行。。。

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();
});
...

需要解释吗?不需要就不用往下看了

  1. 全局状态管理,存储请求的controller
  2. axios拦截器中判断,如果没有switchPageNotCancelRequest参数,则在请求拦截中储存此请求的controller
  3. 在路由拦截前置守卫中,通过遍历store中的controllers,调用controller.abort()取消上个页面的全部请求

相关链接

axios取消请求

vue-router beforeEach

pinia中文文档

完~