【每日一题】为什么使用 setTimeout 实现 setInterval?
前端印记
共 2090字,需浏览 5分钟
·
2021-09-02 01:55
人生苦短,总需要一点仪式感。比如学前端~
分析
setInterval 的作用是每隔一段指定时间执行一个函数,但是这个执行不是真的到了时间立即执行,它真正的作用是每隔一段时间将事件加入事件队列中,只有当目前的执行栈为空的时候,才能去事件队列中取出事件执行。
所以可能会出现这样的情况:若当前执行栈执行的时间很长,导致事件队列里边积累多个定时器加入的事件,当执行栈结束的时候,这些事件会依次执行,因此可能就不能实现“到间隔一段时间执行”的效果。
针对 setInterval 的这个缺点,我们可以使用 setTimeout 递归调用来模拟 setInterval,这样我们就能确保实现“一个事件结束了、才触发下一个定时器事件”的效果,以解决了 setInterval 的问题。
模拟实现
接下来我们使用 setTimeout 模拟实现 setInterval,思路是使用递归函数,不断地执行 setTimeout
从而达到 setInterval
的效果。
简单实现
代码实现
function mySetInterval(fn, interval) {
// 设置递归函数,模拟定时器执行。
function callback() {
fn();
setTimeout(callback, interval);
}
// 启动定时器
setTimeout(callback, interval);
}
执行测试
var i = 0;
mySetInterval(() => {
i++;
console.log(i, '测试打印')
}, 1000);
进阶版:控制是否继续执行
function mySetInterval(fn, interval) {
// 控制器,控制定时器是否继续执行
var timer = {
flag: true,
};
// 设置递归函数,模拟定时器执行。
function callback() {
if (timer.flag) { // 判断是否继续执行
fn();
setTimeout(callback, interval);
}
}
// 启动定时器
setTimeout(callback, interval);
// 返回控制器
return timer;
}
// 使用
let timer = mySetInterval(() => {
console.log(123)
}, 1000)
setTimeout(() => {
timer.flag = false
}, 4000)
让我们一起携手同走前端路!
关注公众号回复【加群】即可
评论