前端终止请求封装

220 阅读1分钟

axios版本v0.22.0版本后可以使用fetch API 方式—— AbortController 取消请求。

官网说明:AbortController 接口的只读属性 signal 返回一个 AbortSignal 实例对象,该对象可以根据需要处理 DOM 请求通信,既可以建立通信,也可以终止通信。

我理解的在请求初始化之后会在options传入signal作为一个“标志”,从而将controller和请求串联起来,从而请求取消。

let controller;

const api = axios.create({
    baseURL: '/api',
    timeout: 30000,
    responseType: 'json'
})

export function get(url, params = {}) {
    try {
        if (controller) {    //第一次进入跳过
            controller.abort() 
        }
        controller = new AbortController()
        const signal = controller.signal
        return api({
            url,
            method: 'GET',
            params,
            signal
        })
    } catch (error) {
        console.error('get:', error)
    }
}

最后被中断的请求并不会消失而是会有个canceled的状态

b284ed6a1d436a6d0dc478cad95e9e7.jpg 58c8e3f1e29af5aae57074cc1ce4b7a.jpg

全局封装

let urlHref = window.location.pathname  // 当前url
let urlList = []  // url列表
let flag = false  // 是否中断
let map = new Map() 
export function callApi(url, config = {}) {
    try {
        c
        if (window.location.pathname !== urlHref) { // 页面更换->初始值
            urlHref = window.location.pathname
            urlList = []
            map = new Map()
        }
        urlList.push(url) // 将当前接口push

        // 校验url算法
        if (!urlList.length) {  // 兜底
            flag = false
        }
        for (let i in urlList) {  // 遍历当前url列表,供map查询
            if (map.has(url)) { // 如果当前url列表已存在当前的url路径,则将执行中断。此操作需删除掉当前的这一个url
                map.delete(url)
                urlList.pop()
                flag = true
            } else {  // 不存在则将当前的url储存到map
                map.set(urlList[i], i)
                flag = false
            }
        }

        // 是否中断
        if (flag) { // 请求中断(相同接口)
            if (controller) {
                controller.abort()  // 中断 
            }
            controller = new AbortController()
            return api({
                url,
                method: 'GET', // default get
                ...config,
                signal: controller.signal // 中断"标志"
            })
        } else {  // 无需中断(初次访问\多个不同接口)
            controller = new AbortController()
            return api({
                url,
                method: 'GET', // default get
                ...config,
                signal: controller.signal
            })
        }
    } catch (error) {
        console.error('callApi:', error)
    }
}