当前位置: 首页 > 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.dtcms.com/a/363714.html

相关文章:

  • LeetCode 844.比较含退格的字符串
  • Spring 事务原理解析:AOP 的一次完美落地
  • 高校党建信息管理系统的设计与实现-(源码+LW+可部署)
  • wpf模板之DataTemplate
  • HTML第五课:求职登记表
  • apache-jmeter-5.1.1安装部署与使用教程(小白一看就会)​
  • Docker启动两个Redis镜像并配置一主一从
  • Spring Boot数据脱敏方案
  • sed相关知识
  • C++基础组件
  • 【值得收藏】手把手教你用PyTorch构建Transformer英汉翻译系统,从训练到推理
  • 小程序蓝牙低功耗(BLE)外围设备开发指南
  • C++革命性新特性:默认实例导出(exportDefault)让单例模式变得无比简单!
  • Vue2 入门(一)介绍及Demo项目创建
  • GISBox内置免费GIS服务器:地形服务发布与应用全指南
  • ChartView的基本使用
  • Redis 的压缩列表:像快递驿站 “紧凑货架“ 一样的内存优化结构
  • Redis-底层数据结构篇
  • 8.30美团技术岗算法第二题
  • 【C++】15. ⼆叉搜索树
  • WordPress.com 和 WordPress.org 之间的区别说明
  • 系统架构——过度设计
  • IO_HW_9_2
  • 教你 Centos 如何离线安装 rlwrap 插件(内网环境)
  • MATLAB矩阵及其运算(三)矩阵的创建
  • 一文搞懂:0-1整数规划与蒙特卡罗模拟(附MATLAB代码详解)
  • 命令行文本处理小工具:cut、sort、uniq、tr 详解与应用
  • 从零开始的python学习——函数(2)
  • shell复习(2)
  • Flutter环境搭建全攻略之-windows环境搭建