一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

Vue Options API如何使用 destroyed 钩子清除未完成的异步请求

时间:2026-09-06 15:52:47 编辑:袖梨 来源:一聚教程网

应在 beforeDestroy 中主动取消异步请求,而非依赖 destroyed 钩子;fetch 用 AbortController.signal,axios 用 CancelToken,并在 catch 中判断取消错误,同时结合 this._isDestroyed 防止响应后更新已销毁组件。

Vue 2 的 destroyed 钩子不是清除异步请求的合适时机——它已是组件销毁的最后一刻,此时请求可能早已完成或仍在运行,但更新数据已无意义,甚至会触发“Avoid mutating a prop directly”或“Cannot set property of null”类警告。真正该做的是在请求发出时就建立可取消机制,并在 beforeDestroy 中主动中断。

用 AbortController 主动中止 fetch 请求

现代浏览器原生支持 AbortController,它是清理未完成 fetch 请求最直接、标准的方式:

  1. data 中声明 abortController: null
  2. mountedcreated 发起请求前新建控制器:this.abortController = new AbortController()
  3. signal 传入 fetch 选项:fetch(url, { signal: this.abortController.signal })
  4. beforeDestroy 中调用 this.abortController.abort(),触发 AbortError 并终止请求

axios 请求需配合 CancelToken(Vue 2 兼容方案)

若使用 axios ≤ 0.20.x,可用 CancelToken 实现类似效果:

  1. 在 data 中定义 cancelTokenSource: null
  2. 发起请求前:this.cancelTokenSource = axios.CancelToken.source()
  3. 请求配置中加入:cancelToken: this.cancelTokenSource.token
  4. beforeDestroy 中执行:if (this.cancelTokenSource) this.cancelTokenSource.cancel('Component destroyed')
  5. 注意在 catch 中判断是否为取消错误:if (axios.isCancel(error)) { /* 忽略 */ } else { /* 处理真实错误 */ }

避免依赖 destroyed 做清理

destroyed 钩子执行时,组件实例已解绑,this.$datathis.$el 等均不可靠,且无法阻止 Promise.then 的执行。即使你在里面调用 abort(),也大概率晚于请求响应:

  1. 响应到达后若尝试 this.xxx = ...,Vue 已不响应,控制台报错
  2. 定时器、事件监听器等资源也应统一在 beforeDestroy 清理,而非拖到 destroyed
  3. destroyed 仅适合记录日志、上报销毁埋点等无副作用操作

补充:Promise 状态不可逆,需逻辑兜底

即使中止了请求,Promise 本身仍会进入 catch 分支。因此业务代码中要确保:

  1. 不在 then 中直接修改响应式数据,先校验组件是否还存活:if (!this._isDestroyed) this.data = res
  2. Vue 2 提供 this._isDestroyed 内部属性(非公开但稳定可用),可用于安全判断
  3. 更健壮的做法是封装请求函数,自动跳过已销毁组件的赋值操作

热门栏目