setInterval设为50ms却以约1500ms执行,求技术解决方案
问题分析与解决方案
你的定时器间隔异常、动画不流畅的问题,主要是由几个代码逻辑和性能问题导致的,咱们一步步拆解并修复:
核心问题根源
- 定时器堆积阻塞主线程:在
gamerule函数中,每次width < 1时都会新建一个setInterval(ser, 1000),但从未清理旧的定时器。随着运行次数增加,大量重复定时器会抢占主线程资源,直接导致setInterval(gamerule, 50)无法按时执行。 - 重复定义函数导致逻辑混乱:你在点击事件和
gamefunc里各定义了一次res函数,后面的定义会覆盖前面的,这会让旋转复位逻辑执行混乱,间接拖慢整体代码节奏。 - 状态变量未更新:
rotated变量初始设为false后从未修改,所有旋转操作都固定为22度,既达不到晃动效果,还会造成不必要的重绘开销。 - 频繁DOM操作触发重排:短时间内反复修改元素的尺寸和旋转属性,会让浏览器频繁重排重绘,进一步阻塞主线程,拉长定时器的实际执行间隔。
修复后的优化代码
我针对上述问题做了针对性调整,同时优化了代码结构和性能:
// 统一初始化变量,用let/const提升可读性 let rotated = false; let height = 24.6; let width = 15; let points = 0; const cutvalw = 1; const cutvalh = 1.64; let val = 10; let serTimer = null; // 存储定时器实例,方便后续清理 // 缓存DOM元素,避免重复查询DOM const boxEl = document.querySelector("#box"); const contEl = document.getElementById("cont"); // 统一的旋转复位函数,避免重复定义 function resetRotation() { // 现代浏览器只需标准transform属性,无需写多前缀 boxEl.style.transform = "rotate(0deg)"; } // 点击事件处理逻辑 boxEl.addEventListener("click", function () { width -= cutvalw; height -= cutvalh; // 切换旋转状态,实现真正的晃动切换 rotated = !rotated; const deg = rotated ? 22 : 0; boxEl.style.transform = `rotate(${deg}deg)`; setTimeout(resetRotation, 140); }); // 游戏规则核心逻辑 function gamerule() { boxEl.style.width = `${width}%`; boxEl.style.height = `${height}%`; if (width < 1) { // 重置尺寸 width = 15; height = 24.6; contEl.style.pointerEvents = "none"; // 先清理旧定时器,避免堆积 if (serTimer) clearInterval(serTimer); serTimer = setInterval(() => { contEl.style.pointerEvents = "all"; // 执行后立即清理定时器,防止重复触发 clearInterval(serTimer); serTimer = null; }, 1000); points++; } } // 自动晃动逻辑 function gamefunc() { if (val >= 10) { width -= 0.5; height -= 0.5; rotated = !rotated; const deg = rotated ? 22 : 0; boxEl.style.transform = `rotate(${deg}deg)`; setTimeout(resetRotation, 140); val = 9; setTimeout(() => { val = 10; }, 1000); } } // 启动定时器 setInterval(gamerule, 50); setInterval(gamefunc, 500);
关键优化点说明
- 缓存DOM元素:避免每次函数执行都重复查询DOM,减少性能开销。
- 合并重复函数:将两个
res函数合并为resetRotation,彻底解决函数覆盖问题。 - 定时器生命周期管理:创建新定时器前先清理旧的,执行完成后及时销毁,避免定时器堆积。
- 修复状态变量:在点击和自动晃动时切换
rotated值,实现真正的晃动效果。 - 简化CSS属性:去掉冗余的浏览器前缀,现代浏览器已支持标准
transform属性。 - 避免嵌套函数:把嵌套的函数改为箭头函数,减少作用域混乱问题。
这些调整应该能解决你定时器间隔异常的问题,让动画恢复流畅。
内容的提问来源于stack exchange,提问作者Benn
相关产品推荐
相关产品推荐

