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.pswp.cn/bicheng/95671.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/95671.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Django get_or_create 方法详解

get_or_create 是 Django ORM 中的一个非常常用的方法,它用于获取数据库中的一个对象,如果该对象不存在,则创建一个新的对象并返回。 方法签名: Model.objects.get_or_create(defaultsNone, **kwargs)参数解释: defaul…

LangChain 文档问答系统中高级文本分割技术

告别语义断裂:LangChain 文档问答系统中高级文本分割技术深度指南 文章目录 引言:问题的根源——为何精准的文本分割是 RAG 系统的命脉? 第一部分:探本溯源——剖析 LangChain 默认分割器的“机械之困” 机制解析:语法驱动的“暴力”切分 问题场景化展示:语义、上下文与结…

Web2 vs Web3--差异一看就懂

互联网技术的浪潮不断推动着我们从Web2时代向Web3时代迈进。这两个时代在技术架构、用户体验、数据所有权等方面有着显著的差异。本文将为您详细解析Web2与Web3之间的差异,并探讨它们如何塑造我们的数字生活。 定义 Web2,即第二代互联网,以其…

深入解析MongoDB内部架构设计

MongoDB内部构造详解 MongoDB作为一款流行的NoSQL数据库,其内部构造设计独特且高效。以下从多个维度详细解析MongoDB的内部架构和核心组件。 一、整体架构 MongoDB采用分布式架构设计,主要包含以下核心组件:应用层:应用程序通过语…

ubuntu12.04安装opencalib手动标定并使用自己的数据

ubuntu22.04安装opencalib手动标定并使用自己的数据 一、OpenCalib的部署使用 1、基本信息 官网链接: https://github.com/PJLab-ADG/SensorsCalibration/tree/v0.2 (官网下载的zip文件是有问题的,不建议到官网下载) 参考链接: https://blog.csdn.net/qq_49959714/arti…

scss 转为原子css unocss

文章目录前言🎯 **方案一:混合模式 (推荐)**🎯 **方案二:语义化组件类**🎯 **方案三:CSS 模块化**🎯 **方案四:BEM 命名规范**💡 **推荐做法**前言 记录让c4 从scss 转为…

【面试题】生成式排序了解吗?

生成式排序是搜索排序的前沿方向,核心思想是利用生成式模型的能力来改善排序效果。 技术实现方式:序列到序列重排序 将候选文档列表作为输入序列使用encoder-decoder模型生成重排后的文档序列优势:能捕捉文档间的全局相关性生成式特征提取 使…

【系统架构设计(15)】软件架构设计一:软件架构概念与基于架构的软件开发

文章目录一、核心思想二、软件架构概念:系统设计的高级抽象三、软件架构设计与生命周期:架构在开发流程中的演进四、架构描述语言ADL:架构的标准化表达五、41视图:多角度的架构展现六、基于架构的软件开发概念:架构驱动…

文件系统-哈希结构文件

一、核心思想哈希文件的核心思想非常简单直接:通过一个计算(哈希函数),将记录的键(Key)直接转换为该记录在磁盘上的物理地址(通常是块地址),从而实现对记录的快速存取。它…

一文吃透 C#中异步编程Task

一文吃透 C#中异步编程Task 一、Task 是什么 二、推荐使用场景 三、Demo:Task 的核心用法 1. 最常用的启动方式Task.Run 2. task完成状态与结果获取 3. 多个任务怎么等?Wait/WaitAll/WaitAny 4. 任务想中途停掉?取消与异常处理 四、必备 API 速查表 五、避坑指南、注意事项 …

TDengine TIMETRUNCATE 函数用户使用手册

TDengine TIMETRUNCATE 函数用户使用手册 函数概述 TIMETRUNCATE 是 TDengine 中的一个时间处理标量函数,用于将时间戳按照指定的时间单位进行截断操作。该函数在时间数据聚合、分组和统计分析中非常有用,特别适用于智能电表等时序数据的分析场景。 语法…

KSZ8081寄存器介绍

一、寄存器概览KSZ8081MNX/RNB 支持 IEEE 802.3 标准的 MII 管理接口(MDIO),寄存器地址范围为 0x00 - 0x1F,其中寄存器 0x00 - 0x08 为 IEEE 标准寄存器,0x09 - 0x1F 为扩展功能寄存器。寄存器按功能可分为基本控制与状…

力扣190:颠倒二进制位

力扣190:颠倒二进制位题目思路代码题目 颠倒给定的 32 位无符号整数number的二进制位。 思路 思路很简单,我们只需要得到number从低位到高位的每一个二进制位再把二进制位移到颠倒的res的对应二进制位即可,例如number的最低位为1那么res的最高位即1&a…

鸿蒙NEXT交互机制解析:从输入设备到手势响应的全面指南

深入探索鸿蒙NEXT的交互设计,掌握下一代人机交互核心技术在智能设备无处不在的今天,一个操作系统的交互设计质量直接影响着用户体验。鸿蒙NEXT作为华为推出的新一代操作系统,在交互设计上带来了许多创新和突破。本文将全面解析鸿蒙NEXT的交互…

通过IDEA写一个服务端和一个客户端之间的交互

服务端代码:WebSocketConfig代码package org.example.hufamessagedemo;import org.springframework.context.annotation.Configuration; import org.springframework.web.socket.config.annotation.*;Configuration EnableWebSocket public class WebSocketConfig i…

玩客云刷机Armbian + CasaOS,轻nas系统,以及扩展

网上太多的教程,综合了一下,自己一边参考一边尝试,昨天晚上做的,感觉今天快忘了,记录一下,少走弯路。 随着矿潮的退去,市场上涌现出了众多所谓的“矿渣盒子”,这些设备往往因为价格低…

【Linux】环境变量与程序地址空间详解

前言:欢迎各位光临本博客,这里小编带你直接手撕Linux程序地址空间,文章并不复杂,愿诸君耐其心性,忘却杂尘,道有所长!!!! **🔥个人主页&#xff1a…

机器学习 - Kaggle项目实践(8)Spooky Author Identification 作者识别

Spooky Author Identification | Kaggle Approaching (Almost) Any NLP Problem on Kaggle (参考) Spooky Author Identification | Kaggle (My work) 根据三位的一些作品训练集,三分类测试集是哪个作家写的概率。 …

[frontend]WebGL是啥?

对于初学者来说,通常的建议是: 不要直接从原生 WebGL 开始,而是先使用一个基于 WebGL 的高级框架或库,最著名的就是 Three.js。 webgl是啥 three.js是啥? Three.js 封装了 WebGL 的复杂细节,提供了更简单、…

[光学原理与应用-400]:设计 - 深紫外皮秒脉冲激光器 - 元件 - 声光调制器AOM

声光调制器(Acousto-Optic Modulator, AOM)是深紫外皮秒脉冲激光器中实现脉冲主动控制、频率稳定及光束管理的核心元件。其通过声波与光波的弹光相互作用,在皮秒时间尺度内实现激光强度、频率或传播方向的精准调制。以下从工作原理、关键性能…