前端面试 P051:副作用清理与过期请求
来源:方格前端讲面试 · 9.Vue的副作用清理逻辑,9 分 57 秒。
回看定位:01:10 清理时机 · 03:09 清理注册 · 05:55 过期请求 · 07:56 作用域
清理在失效与停止时发生
watch/watchEffect 的一次执行建立了资源,下一次重新运行前应先清理旧资源;停止 watcher 或其所属有效作用域销毁时,也需要清理。
import { ref, watchEffect, nextTick } from 'vue';
const period = ref(1000);
const stop = watchEffect(onCleanup => {
const timer = setInterval(() => {}, period.value);
onCleanup(() => clearInterval(timer));
});
period.value = 2000;
await nextTick();
stop();
effect 中读取 period 建立依赖;先前 interval 在重跑前移除,最后 stop 再清除当前 interval。仅停止 watcher 不会自动猜到你启动了哪些浏览器资源,所以必须注册对应清理动作。
onInvalidate、onCleanup 与版本
视频把传入回调的清理注册函数命名为 onInvalidate,这个参数名可以自行选择。当前文档常叫 onCleanup,不需要因此寻找一个同名可导入的 onInvalidate API。
watch 的第三个回调参数与 watchEffect 的首个参数可注册清理。Vue 3.5 还有 onWatcherCleanup,必须在 watcher 同步执行阶段调用,不能等 await 之后才注册;二者约束不要混记。
搜索旧响应覆盖新响应
每次请求创建 AbortController,在清理时 abort;同时保存当前执行是否有效的标记或序号,只允许最新执行提交数据、错误与 loading 状态。
取消并不意味着服务器已撤销操作,某些数据源也不支持取消。身份标记仍能阻止过期结果写入界面。catch 中不要把主动取消当成真正业务错误向用户展示。
如果需要“输入一改变就失效”的严格时序,要结合 watch 调度模式或在输入边界更新序号;不能只靠假定默认异步 watcher 在任何竞态里都先运行。
作用域与卸载
同步 setup 中建立的 watcher 通常自动随组件停止;异步回调中创建的 watcher 不一定绑定同一作用域,应保存 stop 或重新安排创建时机。组合式函数可用 onScopeDispose 把其他资源绑定到当前作用域。