Axios使用CancelToken取消重复请求

处理重复请求:没有响应完成的请求,再去请求一个相同的请求,会把之前的请求取消掉
在这里插入图片描述
新增一个cancelRequest.js文件

import axios from "axios"
const cancelTokens = {}

export const addPending = (config) => {
    const requestKey = getRequestKey(config)
    if (cancelTokens[requestKey]) {
        cancelTokens[requestKey].cancel('cancel request')
    }
    const source = axios.CancelToken.source()
    cancelTokens[requestKey] = source
    config.cancelToken = source.token
}

export const deletePending = (res) => {
    const requestKey = getRequestKey(res.config)
    if (cancelTokens[requestKey]) {
        delete cancelTokens[requestKey]
    }
}

const getRequestKey = (config = {}) => {
    return config.url + config.method + JSON.stringify(config.params, config.data)
}

request.js

import axios from "axios"
import { baseUrl } from "@/config"
import { addPending, deletePending } from "./cancelRequest"
const service = axios.create({
    baseURL: baseUrl,
    timeout: 100000,
})
service.interceptors.request.use(
    config => {
        addPending(config)
        return config
    },
    error => {
        return Promise.error(error)
    }
)

service.interceptors.response.use(
    success => {
        deletePending(success)
    },
    error => {
        deletePending(error)
    }
)

export default service
### 使用 Axios 封装取消重复请求 为了实现取消重复请求的功能,可以利用 `axios` 提供的 `CancelToken` 和拦截器机制。下面是一个完整的解决方案,展示了如何通过自定义方法来管理待处理的请求并确保不会发出重复请求。 #### 创建全局变量存储待处理请求 首先声明一个 Map 对象用于保存当前所有的挂起请求及其对应的取消函数: ```javascript const pendingRequests = new Map(); ``` #### 定义辅助工具类 接着编写几个帮助函数以便于后续逻辑调用: - **getPendingRequestKey**: 构建唯一键名作为标识符; - **addPendingRequest**: 向集合中添加新成员; - **removePendingRequest**: 移除已完成或被终止的任务; ```javascript // 获取唯一的请求key function getPendingRequestKey(config) { return [ config.method, config.url, JSON.stringify(config.params), JSON.stringify(config.data) ].join('&'); } // 添加到pending队列里 function addPendingRequest(config, cancelFn) { const key = getPendingRequestKey(config); if (!pendingRequests.has(key)) pendingRequests.set(key, cancelFn); } // 从pending队列删除 function removePendingRequest(config) { const key = getPendingRequestKey(config); if (pendingRequests.has(key)) { const cancelFn = pendingRequests.get(key); cancelFn('Duplicate request was cancelled.'); pendingRequests.delete(key); } } ``` #### 配置 axios 请求/响应拦截器 接下来设置两个拦截器分别负责在每次发起 HTTP 调用前检查是否有相同 URL 正处于等待状态以及接收服务器返回的数据后清理掉对应条目: ```javascript import axios from 'axios'; // 设置默认超时时间和基础路径等参数... axios.defaults.timeout = 5000; axios.defaults.baseURL = '/api/'; // 请求拦截器 axios.interceptors.request.use( config => { // 判断是否允许取消 if (config.allowCancel !== false) { // 检查是否存在相同的请求 removePendingRequest(config); // 新增cancel token config.cancelToken = new axios.CancelToken(cancel => { addPendingRequest(config, cancel); }); } return config; }, error => Promise.reject(error) ); // 响应拦截器 axios.interceptors.response.use( response => { removePendingRequest(response.config); return response; }, error => { if (axios.isCancel(error)) { console.warn(`Request canceled: ${error.message}`); } else { // 清理失败的请求 removePendingRequest(error.config || {}); } return Promise.reject(error); } ); ``` #### 发送带有取消功能的 GET 请求实例 最后展示一段实际应用场景下的代码片段,这里假设有一个获取加密货币行情数据的需求场景: ```javascript async function fetchCryptoData(params) { try { const result = await axios({ method: 'GET', url: '/crypto/prices', // API endpoint params, allowCancel: true // 开启此选项以启用去重特性 }); console.log(result.data); // 输出结果 return result; } catch (e) { throw e; } } ``` 上述代码实现了基于 `axios` 库的一套简单而有效的防止重复提交方案[^2]。每当有新的请求到来时,程序会先尝试查找是否存在完全一致的历史记录——即同一 URI 下携带相等查询字符串与 body 参数组合而成的关键字存在于 `pendingRequests` 中;一旦发现匹配项则立即执行关联的取消指令,并更新映射表使其保持最新状态。反之亦然,在正常情况下新增加一条记录直至收到服务端反馈为止才会将其清除出去。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值