通过取消请求解决请求竞态问题

什么是请求竞态?

  • 请求竞态(Race Condition)是指在前端开发中,当多个异步请求(如 AJAX、Fetch 或 Axios 请求)同时发起时,由于网络延迟或服务器响应时间不同,导致后发起的请求可能比先发起的请求更早返回,从而使得最终显示的数据不符合预期顺序。
  • 简而言之就是:接口的请求顺序不一定等于接口的返回顺序。
  • 例如下图

当我快速点击按钮1、按钮2时,由于接口的响应速度不一定一样,因此导致页面上显示的是page1,这就是一个典型的请求竞态

如何解决?

解决这个问题,我这里提供两种方案:

  1. 前端每次发送请求时都带一个requestId给后端,后端返回结果时也把这个requestId返回过来,接口响应数据后,请端通过最后一次都requestId来找到后端最新的接口返回的数据,这种方案有个缺点就是需要去动服务端。
  2. 纯前端利用abort来取消请求,每次发送请求时先判断上一次是不是请求过相同的接口了,如果有就取消上一次的请求。

这里简单提一下一些ajax取消请求的方法

  1. xhr利用abort()取消

2.fetch利用AbortController

由于现在的项目大多都是用axios,因此我这里讲axios如何取消请求

js 复制代码
import axios from 'axios'

const requestMap = new Map()
const pushRequest = (config) => {
  const { url2, method } = config
  const uniq = `${url2}_${method}` // 自行调整
  // 当我们每次发起请求时,先去map中找是否有相同的请求,如果有则讲上一次的请求取消掉
  if (!requestMap.has(uniq)) {
    const controller = new AbortController()
    config.signal = controller.signal
    requestMap.set(uniq, controller)
  } else {
    const controller = requestMap.get(uniq)
    controller.abort() // 取消请求
    requestMap.delete(uniq) // 删除controller
  }
}
const removeRequest = (config) => {
  const { url2, method } = config
  const uniq = `${url2}_${method}`
  if (requestMap.has(uniq)) {
    requestMap.delete(uniq)
  }
}
const request = axios.create({
  baseURL: 'http://localhost:12306/',
})
try {
  request.interceptors.request.use(
    (config) => {
      pushRequest(config)
      console.log('map', requestMap)
      console.log('Request Interceptor', config)
      return config
    },
    (err) => {
      console.log('Request Error', err)
      return Promise.reject(err)
    },
  )
} catch (error) {
  console.log('Request Error', error)
}
request.interceptors.response.use(
  (response) => {
    removeRequest(response.config)
    console.log('Response Interceptor', requestMap)
    return response
  },
  (err) => {
    return Promise.reject(err)
  },
)
export default request
相关推荐
子兮曰5 天前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰5 天前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
前端小万5 天前
写公众号赚了 3000 块后,我做了一款叫 "一键成稿" 的软件
前端·微信小程序
爱勇宝5 天前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
三十而立洋5 天前
Cookie 详解:从产生到安全,一次讲透
前端·javascript
晨米酱5 天前
AGENTS.md:Agent 的上下文策略层
面试·架构·agent
卡布鲁5 天前
把一个 Vite + Vue3 应用塞进 qiankun (React + Umi3) 主站:十个坑的复盘
前端·javascript·react.js
彧azz5 天前
Linux 环境下 Redis 学习总结:数据类型、持久化、锁、事务、主从与缓存问题
linux·redis·笔记·学习·面试
汉堡大王95275 天前
Jev:不是聊天机器人, 而是一个智能 if 语句
前端·人工智能·后端
梦想很大很大5 天前
从运行事实到回归证据:Workrun 的 Telemetry 与 Evaluation 实践
前端·人工智能·后端