JS骰子动画setInterval定时执行异常问题排查
问题根因
你写的setTimeout(clearInterval(myInterval),2000)存在传参错误:setTimeout的第一个参数需要接收延迟到期后才执行的函数引用,但你传入的是clearInterval(myInterval)这个立即执行的函数调用语句。
实际运行时的逻辑完全不符合你的预期:
- 刚执行完
setInterval创建好50ms触发一次的滚动定时器、拿到定时器IDmyInterval,JS引擎就立刻执行了clearInterval(myInterval),刚创建的定时器瞬间就被销毁,根本没机会触发roll_dice更新骰子图片 - 最终
setTimeout拿到的第一个参数是clearInterval执行后的返回值undefined,等2秒延迟到期后什么操作都不会执行
这也能解释为什么你注释掉这行代码后,骰子就能正常滚动——因为定时器不会被立刻清除了,只是少了到期自动停止的逻辑。
这类错误是JS定时器的高频使用误区:只要在
setTimeout/setInterval的第一个参数位置给函数加了括号(),就代表立刻执行该函数,传入的是函数执行后的返回值,而非待延迟执行的函数本身。
修复方案
将setTimeout的第一个参数改为包裹清除逻辑的回调函数即可,不要直接写函数调用:
function animate_dice() { let myInterval = setInterval(roll_dice, 50); // 传入函数引用,等2000ms到期后再执行清除逻辑 setTimeout(() => { clearInterval(myInterval); // 动画停止后额外执行一次点数生成,保证最终停在随机结果上 roll_dice(); }, 2000); }
如果需要兼容不支持ES6箭头函数的老旧环境,可以换成普通匿名函数写法:
setTimeout(function() { clearInterval(myInterval); roll_dice(); }, 2000);
修复后逻辑就会符合预期:2秒的动画周期内每50ms刷新一次骰子状态实现滚动效果,到期自动停止在最终的随机点数上。
内容的提问来源于stack exchange,提问作者Dave Moutardier
相关产品推荐
相关产品推荐

