clearInterval是否终止当前执行?Vue 2.0定时任务技术问询
Vue 2.0 定时任务与异步请求终止问题
我在Vue 2.0项目里用这段代码实现每分钟调用一次this.refreshState():
this.scheduler = setInterval(() => this.refreshState(), 60 * 1000)
之后要确保定时循环停止的同时,终止任何正在运行的this.refreshState()实例(哪怕它还在执行过程中)。目前我用的是:
clearInterval(this.scheduler)
查了MDN还是有疑问:clearInterval会不会终止当前正在执行的任务?
附refreshState的代码:
refreshState: function () { // 调用后端API axios.get("/api/refreshState") .then(response => { this.states = response.data.states }) .catch((err) => console.log(err)) }
我的使用场景是这样的:
alterState: function (incremental_state) { clearInterval(this.scheduler) // 这里这么写对吗? axios.post("/api/alterState", incremental_state) .then(() => { this.refreshState() this.scheduler = setInterval(() => this.refreshState(), 60 * 1000) }) .catch((err) => { console.log(error) }) }
需要保证退出alterState时,this.states能正确反映新增的增量状态。
核心结论:clearInterval不会终止正在执行的异步任务
clearInterval仅负责停止后续定时任务的触发,完全无法影响当前已经启动的refreshState函数——尤其是里面的axios异步请求:一旦请求发送出去,就算你清除了定时器,这个请求仍会继续执行,完成后依然会修改this.states,这会导致alterState执行后,旧请求的结果可能覆盖刚更新的状态值。
完整解决方案:给axios请求添加取消机制
要彻底终止正在运行的refreshState实例,需借助axios的取消令牌(CancelToken)中断未完成的API请求,具体步骤如下:
- 在组件的
data中定义取消令牌相关变量:
data() { return { scheduler: null, refreshCancelSource: null } }
- 修改
refreshState方法,每次调用前取消未完成的旧请求:
refreshState: function () { // 取消之前未完成的请求 if (this.refreshCancelSource) { this.refreshCancelSource.cancel('取消旧的refreshState请求') } // 创建新的取消令牌源 this.refreshCancelSource = axios.CancelToken.source() axios.get("/api/refreshState", { cancelToken: this.refreshCancelSource.token // 绑定取消令牌 }) .then(response => { this.states = response.data.states }) .catch((err) => { // 取消请求的错误无需打印 if (!axios.isCancel(err)) { console.log(err) } }) }
- 优化
alterState方法,确保同时清理定时器和当前请求:
alterState: function (incremental_state) { // 停止定时任务 clearInterval(this.scheduler) // 取消正在执行的refreshState请求 if (this.refreshCancelSource) { this.refreshCancelSource.cancel('alterState执行,取消旧请求') } axios.post("/api/alterState", incremental_state) .then(() => { this.refreshState() // 获取最新状态 this.scheduler = setInterval(() => this.refreshState(), 60 * 1000) // 重启定时任务 }) .catch((err) => { console.log(err) // 可选:请求失败时恢复定时任务,根据业务需求调整 this.scheduler = setInterval(() => this.refreshState(), 60 * 1000) }) }
- 组件销毁时清理资源:
beforeDestroy() { clearInterval(this.scheduler) if (this.refreshCancelSource) { this.refreshCancelSource.cancel('组件销毁,取消请求') } }
效果说明
- 调用
alterState时,先停掉定时任务避免后续触发新请求,同时取消当前未完成的refreshState请求,防止旧结果覆盖新状态 - 等
alterState的POST请求成功后,主动调用refreshState获取最新状态,再重启定时任务 - 这样就能确保退出
alterState时,this.states是基于最新增量状态更新后的结果,不会被旧异步请求干扰
内容的提问来源于stack exchange,提问作者orville
相关产品推荐
相关产品推荐

