1.setTimeout的延迟是不确定的
delay 参数指定的是将回调函数添加到消息队列的最小延迟时间
如果主线程繁忙,实际延迟大于等于dalay
2.setInterval可能导致任务堆积
直观比喻
想象一下:
- 你有一个传送带(
setInterval),每隔 1 秒放一个包裹(任务)。 - 你是搬运工(JavaScript 主线程),每次搬一个包裹需要 2 秒。
- 结果就是:包裹越来越多,堆积在传送带上。
举个例子:
setInterval(() => {
console.log('start');
// 模拟耗时任务
const start = Date.now();
while (Date.now() - start < 2000) {} //无限循环直到走出循环
console.log('end');
}, 1000);
这里 setInterval 设置了 1 秒执行一次,但每次回调执行 2 秒。实际执行结果会是:
start
end
start
end
start
end
...
- 你会发现“start”之间不会严格间隔 1 秒,而是因为任务在队列里堆积,可能连续执行。
3. 如何避免?
解决思路就是 不要让包裹堆积:
-
方法一:用
setTimeout串行执行function runTask() { console.log("任务开始"); setTimeout(runTask, 1000); // 完成后再等 1 秒 } runTask(); -
方法二:加锁/标志位,任务没完成就不开始下一个
let running = false; setInterval(() => { if (running) return; running = true; console.log("任务开始"); setTimeout(() => { console.log("任务结束"); running = false; }, 2000); }, 1000);