最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
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 请求最直接、标准的方式:
- 在
data中声明abortController: null - 在
mounted或created发起请求前新建控制器:this.abortController = new AbortController() - 将
signal传入fetch选项:fetch(url, { signal: this.abortController.signal }) - 在
beforeDestroy中调用this.abortController.abort(),触发AbortError并终止请求
axios 请求需配合 CancelToken(Vue 2 兼容方案)
若使用 axios ≤ 0.20.x,可用 CancelToken 实现类似效果:
- 在 data 中定义
cancelTokenSource: null - 发起请求前:
this.cancelTokenSource = axios.CancelToken.source() - 请求配置中加入:
cancelToken: this.cancelTokenSource.token -
beforeDestroy中执行:if (this.cancelTokenSource) this.cancelTokenSource.cancel('Component destroyed') - 注意在
catch中判断是否为取消错误:if (axios.isCancel(error)) { /* 忽略 */ } else { /* 处理真实错误 */ }
避免依赖 destroyed 做清理
destroyed 钩子执行时,组件实例已解绑,this.$data、this.$el 等均不可靠,且无法阻止 Promise.then 的执行。即使你在里面调用 abort(),也大概率晚于请求响应:
- 响应到达后若尝试
this.xxx = ...,Vue 已不响应,控制台报错 - 定时器、事件监听器等资源也应统一在
beforeDestroy清理,而非拖到destroyed -
destroyed仅适合记录日志、上报销毁埋点等无副作用操作
补充:Promise 状态不可逆,需逻辑兜底
即使中止了请求,Promise 本身仍会进入 catch 分支。因此业务代码中要确保:
- 不在
then中直接修改响应式数据,先校验组件是否还存活:if (!this._isDestroyed) this.data = res - Vue 2 提供
this._isDestroyed内部属性(非公开但稳定可用),可用于安全判断 - 更健壮的做法是封装请求函数,自动跳过已销毁组件的赋值操作