axios取消重复请求

axios提供了两种取消请求的方式:

1.通过CancelToken.source().token取消

const CancelToken = axios.CancelToken;
const source = CancelToken.source();

axios.get('xxx', {
    cancelToken: source.token
}).catch((error) => {
    if(axios.isCancel(error)) {
        console.log('取消请求')
    } else {
        // 错误处理
    }
})
source.cancel('取消请求');

// 上面是get的

// 下面是post的
axios.post('xxxx', { // 此对象为请求参数
}, {
  cancelToken: source.token
}).catch((error) => {
    if(axios.isCancel(error)) {
        console.log('取消请求')
    } else {
        // 错误处理
    }
})

source.cancel('取消请求');

2.通过CancelToken构造函数取消

const CancelToken = axios.CancelToken;
let cancel;

axios.get('xxx', {
  cancelToken: new CancelToken(function executor(c) {
    cancel = c;
  })
});

cancel();

我们使用的是Vue框架封装axios请求,没看过的可以点击

import { removeToken } from '@/utils/auth'
import { addRequest, removeRequest } from '@/utils/cancelToken'
import router from "@/router";
const CancelToken = axios.CancelToken;
// 我这里的axios放入CDN
// 创建axios实例
const service = axios.create({
    baseURL: process.env.NODE_ENV === 'development' ? '/api' : '/', // url = base url + request url
    timeout: 20000, // 请求超时时间
    headers: {
        'Content-Type': 'multipart/form-data'
    },
    // responseType: 'json',
    // withCredentials: false
})

// 请求拦截器
service.interceptors.request.use(
    config => {
        removeRequest(config); // 在请求开始前,对之前的请求做检查取消操作
        addRequest(config); // 将当前请求添加到 pending 中
        config.url = config.url + `?v=${new Date().getTime()}`;
        return config
    },
    error => {
        return Promise.reject(error)
    }
)

// 响应拦截器
service.interceptors.response.use(
    response => {
        removeRequest(response) // 在请求结束后,移除本次请求
        const res = response.data
        if (res) {
            if (res.code !== 0) {
                ELEMENT.Message({
                    message: res.msg || 'Error',
                    type: 'error',
                    duration: 3 * 1000
                })
                if (res.code === -5) {
                    removeToken() // must remove  token  first
                    router.replace({ path: "/login" });
                }
                return res
            } else {
                return res
            }
        } else {
            ELEMENT.Message({
                message: '接口连接失败,请联系管理员',
                type: 'error',
                duration: 5 * 1000
            })
        }
    },
    error => {
        if (!axios.isCancel(error)) { // 不是手动取消axios请求
            ELEMENT.Message({
                message: error.msg || '请求失败,请联系管理员',
                type: 'error',
                duration: 5 * 1000
            });
        }
        return Promise.reject(error);
    }
)

export default service

cancelToken.js

/**
 * axios取消重复接口请求封装
 */

const pending = new Map(); // 储存请求接口

// 添加请求
const addRequest = (config) => {
    const key = [
        config.method,
        config.url
    ].join('&'); // 拼接map键

    config.cancelToken = config.cancelToken || new axios.CancelToken(cancel => {
        if (!pending.has(key)) {
            pending.set(key, cancel)
        }
    })
}

// 移除请求
const removeRequest = (config) => {
    const key = [
        config.method,
        config.url
    ].join('&'); // 拼接map键

    if (pending.has(key)) { // 如果在 pending 中存在当前请求标识,需要取消当前请求,并且移除
        const cancel = pending.get(key)
        cancel(key)
        pending.delete(key)
    }
}

// 清空请求

const clearRequest = () => {
    for (const [key, cancel] of pending) {
        cancel(key)
    }
    pending.clear()
}

export {
    addRequest,
    removeRequest,
    clearRequest
}
import {clearRequest} from '@/utils/cancelToken'
import router from './router'; // router实例
router.beforeEach((to, from, next) => {
    clearRequest();// 每一个路由的切换都清空pengding(清空map)
    next();
})
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐