10.setTimeout和setInterval的区别以及模拟实现:
setTimeout
:推迟ms后执行一次;(延时器)setInterval
:间隔ms就重复执行。(重复定时器)
使用setTimeout和setInterval会出现误差(感兴趣的小伙伴可以自己测试一下)。
- 出现误差的原因:跟JS的 Event loop有关。(定时器不是同步任务,而是异步任务中的宏观任务)
- 关于事件循环可以参考这篇 动图学习-eventloop
- 定时器中的时间参数不是到点就立即执行,而是到点了再将其回调事件加入事件队列中。
- 执行顺序再根据定时器前面是否还有比它优先级更高的任务队列,如果有则需要等待。
- 解决方案
setInterval
的缺点:
setInterval
会在任务推入异步队列时判断上次异步任务是否被执行,这就会导致 setInterval
在事件循环的时候会出现耗时操作,比如调用异步操作耗时,会导致异步任务不按照期待的时间间隔内执行。
- 使用
setTimeout
模拟setInterval
规避setInterval
的缺点:
- 原因:
setTimeout
是不管上次异步任务是否完成,都会将当前异步任务推入队列。
function mysetInterval(fn, delay) {
let timer = null;
function interval() {
fn();
timer = setTimeout(interval, delay);
}
interval();
return {
cancel: () => {
clearTimeout(timer);
}
}
}
let a = mysetInterval(() => {
console.log(111);
}, 1000)
let b = mysetInterval(() => {
console.log(222)
}, 1000)
- 使用setTimeInterva实现setTimeout:
const mysetTimeout = (fn, delay) => {
const timer = setTimeout(() => {
clearInterval(timer);
fn();
}, delay);
}