当前位置: 首页 > news >正文

Vue + fetchEventSource 使用 AbortController 遇到的“只能中止一次”问题解析与解决方案

前言

在前端项目中,使用 SSE(Server-Sent Events) 长连接去获取实时消息已经很常见了。像 fetchEventSource 这种封装好的工具,可以帮助我们轻松处理流式请求。

不过在实践中,我遇到了一个奇怪的问题:点击按钮触发 SSE 请求时,controller.abort() 只能生效一次,第二次再触发就完全没用了。本文记录一下排查和解决过程。


问题复现

假设有如下代码:

const controller = new AbortController();const onSubmit = () => {// 中止上一轮消息请求controller.abort();ElMessage.success("中止");// 建立新的消息请求fetchEventSource(url, {method: "POST",headers: {"Content-Type": "application/json",},body: JSON.stringify({"name": "小明"}),openWhenHidden: true, // 窗口不可见时保持连接signal: controller.signal,	// 请求控制器:用于中止sse请求的onmessage(ev) {console.log("收到消息", ev.data);},});
};

第一次点击按钮时,能成功中止请求;
但第二次点击时,请求却再也中止不了了。


问题原因

问题的关键在于 AbortController 的 signal 只能使用一次

  • controller.abort() 调用后,controller.signal 就已经被标记为 aborted
  • 下一次再传入同一个 signalfetchEventSource,它会发现这个 signal 已经失效,自然就无法再中止。

也就是说:AbortController 不能复用,每次请求都必须创建新的实例


解决方案

在 Vue 组件中,可以把 controllerref 管理,每次请求时都先 abort 上一个,再创建一个新的

正确写法

import { ref } from "vue";const controller = ref(new AbortController());const onSubmit = () => {// 先中止上一次请求(如果存在)if (controller.value) {controller.value.abort();}// 创建新的 controllercontroller.value = new AbortController();fetchEventSource(url, {method: "POST",headers: {"Content-Type": "application/json",},body: JSON.stringify(body),signal: controller.value.signal,	// 用 ref 给onmessage(ev) {console.log("收到消息", ev.data);},onerror(err) {console.error("错误:", err);}});
};

总结

  • AbortController 是一次性消耗品,不能复用
  • 每次请求前必须 controller = new AbortController()
  • 在 Vue 中用 ref 管理 controller 更加清晰,方便中止和重置。

这样写就能保证:不管点多少次发送按钮,每一次请求都能正确中止。

http://www.xdnf.cn/news/1427293.html

相关文章:

  • 详解 C++ 中的虚析构函数
  • 【系统架构设计(12)】系统运行与软件维护
  • 优选算法的映射之妙:哈希表专题
  • 【数据结构】八大排序之快速排序:分而治之的艺术
  • 从技术架构到经济价值:低代码在企业开发中的成本节约潜力
  • 面试新纪元:无声胜有声,让AI成为你颈上的智慧伙伴
  • Windows远程连接:SSH+RDP+Server
  • 警惕!虚拟货币“赠予”可能被认定为洗钱犯罪
  • NLP模型简介
  • 解决Mac电脑连接蓝牙鼠标的延迟问题
  • 【Python练习题】Python小白必练100题答案-第21-40题
  • 基础思想:动态规划与贪心算法
  • [Dify 专栏] 如何通过 Prompt 在 Dify 中模拟 Persona:即便没有专属配置,也能让 AI 扮演角色
  • 文章阅读与实践 - 延迟双删/分库分表/Spring IOC生命周期/Mysql主从一致优化
  • 一文读懂 LoRaWAN A、B、C类的区别及应用
  • 用 PyTorch 实现食品图像分类:从数据预处理到模型训练与预测
  • Linux电脑怎样投屏到客厅的大电视?支持远程投屏吗?
  • 从Java全栈到前端框架:一场真实的技术面试实录
  • 《Vue进阶教程》(7)响应式系统介绍
  • iOS15如何绕过MDM锁?详细图文教程教你搞定
  • 滚珠导轨在工业制造领域如何实现高效运行?
  • 网络传输的实际收发情况及tcp、udp的区别
  • 电子电气架构 --- 当前企业EEA现状(上)
  • 云计算学习笔记——Linux系统网络配置与远程管理(ssh)篇
  • Java搭建高效后端,Vue打造友好前端,联合构建电子采购管理系统,实现采购流程电子化、自动化,涵盖采购全周期管理,功能完备,附详细可运行源码
  • Node.js 命令行交互王者:inquirer 模块实战指南
  • Pytorch Yolov11目标检测+window部署+推理封装 留贴记录
  • WPF迁移avalonia之图像处理(一)
  • 基于SpringBoot的古典舞在线交流平台
  • C++革命性新特性:默认实例导出(exportDefault)让单例模式变得无比简单!