当前位置:首页 > 文章列表 > 文章 > 前端 > Vue onWatcherCleanup 怎样取消过期请求

Vue onWatcherCleanup 怎样取消过期请求

来源:17golang原创 2026-11-07 00:22:12 0浏览 收藏

Vue 3.5+ 可以在 watch 回调的同步部分调用 onWatcherCleanup,注册一个清理函数,在该轮侦听失效时调用 AbortController.abort() 取消仍在进行的 fetch 请求。关键是每轮创建独立控制器,并在第一个 await 前完成注册。页面状态还应判断本轮是否有效,避免旧请求的结果、错误或 finally 覆盖新状态。

官方地址:https://vuejs.org/

设想搜索框先查询“书架”,随后很快改成“书桌”。后一个请求先返回,前一个却在稍后完成。如果两个回调都直接给列表赋值,页面就可能显示旧关键词的结果。下面把这个现象作为示例场景,拆清根因和处理方式,不把它描述成某次真实线上事故或实测记录。

旧请求覆盖新结果,问题在状态归属

异步响应的返回顺序并不保证与输入顺序一致。侦听器重新执行,也不会自动替你取消前一轮创建的所有异步资源。修复需要同时处理两件事:请求不再需要时取消它;异步回调准备修改页面时,确认它仍属于当前查询。

只给结果加判断仍不够。例如旧请求的 finally 无条件把 loading 设成 false,会让新请求尚未完成时加载提示就消失。错误状态也一样:过期请求的失败信息不应该盖住新结果。因此下面统一用 isCurrent() 判断三类状态。

每轮请求拥有自己的取消控制器

以下是一个 Vue 3.5+ 单文件组件示例。需要项目自行提供同源的 /api/search?q=关键词,并返回包含字符串数组 items 的 JSON;这个接口是应用约定,不是 Vue 内置服务。

watch 回调、onWatcherCleanup 和失效标记属于同一轮侦听作用域。AbortController 通过 AbortSignal 与 fetch 请求关联。每轮分别创建控制器,能够避免共享变量被下一轮覆盖后,清理函数意外取消新请求。Vue 对清理注册的时机要求见侦听器清理文档。

Vue侦听回调清理函数与本轮控制器信号和请求资源的静态关系
静态结构图:每轮 watch 回调独立持有控制器和失效标记,清理函数关联本轮请求资源,不表示请求执行时间线。

结果、错误和加载状态共用有效性判断

这里的当前条件是 query 规范化后的值,本轮条件是回调参数 term,有效标记是 active。isCurrent() 把三者组合成有效性判断,再约束结果状态 items、错误状态 error 和加载状态 loading。这个判断是示例的状态提交规则,和浏览器是否已经结束网络连接是两回事。

cleanup 设置 active 为 false,随后 abort 请求;catch 看到主动取消或过期状态时直接退出。但 JavaScript 仍会执行 finally,所以 finally 也必须保留判断。当前条件比较还避免了条件已经变更、旧回调却准备提交状态时,把旧内容写回页面。

当前条件本轮条件和有效标记共同约束结果错误加载状态
静态说明图:有效性判断同时约束结果、错误和加载状态;页面状态只能由仍匹配当前条件的有效回调提交。
异步位置未经保护的影响示例处理
成功响应旧列表覆盖新列表有效时才设置 items
catch取消被误报为业务失败取消或过期时忽略
finally旧请求关掉新 loading有效时才结束加载

浏览器 abort 能取消未完成的 fetch、响应体读取等操作,见AbortController.abort 文档。它不能撤销已经提交的页面赋值,也不能作为服务端业务回滚机制。对于不接受 signal 的请求库,应使用其取消接口,并继续保留有效性判断。

清理必须在 await 前注册,旧项目可用 onCleanup

onWatcherCleanup API要求在侦听器的同步执行期间调用。不要先 await 请求或异步准备工作,再补注册。那时侦听器上下文可能已经不在,而且请求也可能早已失效。

Vue 3.5 以前的 Vue 3 项目,可以使用 watch 回调第三个参数 onCleanup。以下片段只展示注册方式,省略的请求状态逻辑应沿用上面的 active 和 isCurrent() 保护;不要在同一个回调里重复注册两套相同清理。

// 沿用已有query;第三个参数与当前侦听器实例绑定
watch(() => query.value.trim(), (term, _oldTerm, onCleanup) => {
  if (!term) return
  const controller = new AbortController()

  // 取消注册仍建议紧挨资源创建,避免异步窗口
  onCleanup(() => controller.abort())

  // 这里只演示请求取消,不向页面提交结果
  fetch('/api/search?q=' + encodeURIComponent(term), {
    signal: controller.signal,
  }).catch(cause => {
    if (!controller.signal.aborted) console.error('请求失败', cause)
  })
})

参数形式的 onCleanup 与全局导入函数的限制不同,但资源创建后及时登记仍然更容易维护。不要仅为了让注册不报错而吞掉上下文错误;先确认当前 Vue 版本和注册位置。

用乱序响应场景确认状态属于当前查询

接入已有接口后,可以让读者在开发环境中让第一轮查询响应较慢,再快速切换到第二轮。预期是旧请求被取消或旧回调不再提交状态,第二轮数据不会被旧列表覆盖;如果第二轮仍在等待,旧请求的 finally 不应关闭 loading。再观察 HTTP 错误状态、非法 JSON 或错误 items 格式是否只影响当前查询。

这些是示例的预期行为与检查方法,本文没有执行请求或生成运行截图。fetch 对 HTTP 状态的处理依据见Fetch 使用说明。

取消请求是否等于防抖?

不等于。取消处理已经发出的过期请求,防抖减少开始请求的频率。需要减少查询次数时,可以另行设计防抖,但它不能代替状态归属判断。

组件卸载后还要手动再 abort 一次吗?

同步在 script setup 中创建的侦听器会随组件卸载停止,其清理负责释放本轮资源。如果在异步回调里创建侦听器,需要自行管理停止句柄,不能直接套用组件自动绑定的结论。

为什么不把一个 controller 放在 watch 外面反复使用?

控制器与一次请求作用域对应更清楚。已经中止的信号不能重新变成未中止;共享可变引用还容易让旧轮清理误操作新轮资源。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
Vue defineModel 怎样处理带默认值的绑定Vue defineModel 怎样处理带默认值的绑定
上一篇
Vue defineModel 怎样处理带默认值的绑定
React useActionState 怎样展示异步表单状态
下一篇
React useActionState 怎样展示异步表单状态
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    918次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    923次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    1020次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    1000次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    823次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议 和 隐私政策
返回登录
  • 重置密码