关键是要管理定时器生命周期而非仅创建。需封装定时器工厂函数返回带幂等.cancel()方法的对象,业务侧主动调用取消;避免闭包捕获大型数据或DOM;支持.attach(owner)绑定组件卸载自动清理;元数据用WeakMap弱引用管理。

关键不是“怎么用定时器”,而是“怎么管住它”。只要创建后没清理,哪怕只跑一次,回调里捕获的变量就可能长期驻留内存——尤其在 SPA 页面跳转、组件卸载后还继续执行,是内存泄漏最常见源头。
封装创建 + 显式取消
别裸写 setInterval(() => {...}, 1000)。每次调用都返回一个可管理的对象:
- 用统一工厂函数创建,比如
timerPool.create({ fn, delay, repeat: true }) - 返回对象必须带
.cancel()方法,且该方法幂等(重复调用不报错) - 业务侧拿到 timer 实例后,在退出逻辑中主动调用
timer.cancel()
切断闭包强引用
回调函数里别直接闭包捕获大型数据或 DOM 元素:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 错误写法:
setTimeout(() => render(data), 500)——data被锁死 - 推荐写法:
setTimeout(() => render(getDataById(timerId)), 500),把查数据逻辑抽出去 - 若必须传参,取消时手动清空引用:
timer.cancel = () => { clearInterval(id); data = null; }
绑定生命周期自动清理
靠人记得调 cancel 容易遗漏。给定时器挂载归属对象:
立即学习“Java免费学习笔记(深入)”;
- 支持
.attach(owner),例如传入 React 组件的 cleanup 函数或 Vue 的onBeforeUnmount - 池内部监听 owner 销毁信号,触发批量取消
- 对一次性定时器(
repeat: false),执行完自动从池中移除元数据,不留残留 ID
弱引用管理元数据
池本身别强持有回调或上下文:
- 用
WeakMap关联定时器 ID 和轻量元数据(如状态、描述),避免阻止 GC - 不缓存原始回调函数,也不长期持有
this或组件实例 - 需要查状态时再通过 ID 查表,查不到就视为已销毁

















