如何用 setTimeout 实现 setInterval ?
这是前几天学校学长的一道大厂面试的手写场景编程题!
来跟上节奏!
让我们一起拿下这道大厂面试题!
首先 让我们先深入理解一下seTtimeout和setlnterval
setTineout
setTimeout 是 JavaScript 中用于设置延时执行代码的函数,常用于异步编程。
插入一个知识点 JavaScript 是一个单线程语言,这意味着它在同一时间只能执行一个任务。
setTimeout计时器是异步执行的执行的计时器,这意味只有当主程序执行完之后才会被执行
setTimeout 的语法
setTimeout(callback, time);
callback: 要在延迟时间结束后执行的函数。time: 延迟的时间(以毫秒为单位)。0表示立即执行(实际会有微小的延迟)。
setTimeout(() => {
console.log("Hello, after 2 seconds!");
}, 2000); // 2秒后输出
setTimeout 的执行机制
setTimeout将回调函数加入 任务队列(Task Queue)。- 当主线程的所有同步任务执行完毕后,事件循环(Event Loop)将任务队列中的回调函数推入执行栈中执行。
- 注意: 即使
time设置为0,回调函数也不会立即执行,而是会等待主线程空闲后执行。
来看一段代码理解一下吧
console.log("Start");
setTimeout(() => {
console.log("Timeout callback");
}, 0);
console.log("End");
**输出结果**
Start
End
Timeout callback
那让我们来继续看一下setInterval计时器
setInterval 是 JavaScript 中的另一个计时器方法,用于按指定的时间间隔反复执行某段代码。与 setTimeout 不同的是,setInterval 会周期性地执行回调函数,直到被手动停止
setInterval 的语法
setInterval(callback, time)
和setTimeout计时器一样
-
callback: 每隔指定时间调用的函数。 -
time: 每次执行之间的时间间隔(毫秒)。
基本用法
javascript
复制代码
setInterval(() => {
console.log("Hello, every 2 seconds!");
}, 2000); // 每隔 2 秒输出一次
setInterval也是异步执行的,要等程序的主线程执行完了之后才会被执行
好了,正片开始。面试官:你能用setTimeout实现setInterval嘛?
首先拿到这道题,我应该先思考一下,setTimeout和setIntval这两个计时器之间有什么相同点和差别,再选择合适的算法实现它。
- 相同点:这两个计时器都是设置延时执行代码的函数,都是异步执行。
- 不同点:setTimeout是在指定时间之后执行一次,而setInterval则是反复执行某段代码.
那通过分析我们这里可以看到这两个计时器的功能差不多的,无非一个就执行一次而另一个执行多次。
嗯...那这里适合什么算法呢? 递归 我们这里可以使用递归setTimeout函数反复执行不就实现了setInterval了
让我们正式开始吧!
- 定义customSetInterval函数
- 参数:
- fn:要周期执行的函数
- time:每次执行的时间间隔。 2.设置一个execute()函数:用于辅助递归调用,这是函数会在每次执行时重新设置一个setTimeout函数,实现再次调用自己。
好让我们把它写出来吧
function customInterval(fn, time) {
function execute() {
callback(); // 执行回调函数
setTimeout(execute, time); // 设置下一次调用
}
setTimeout(execute, time); // 初始化定时器
}
// 示例:每隔 1 秒执行一次
customInterval(() => {
console.log("Executing task...");
}, 1000);
面试官:嗯,实现是实现了,能不能再优化一下呢?
好好好,果然面试官不会简单的放过我们
那我们在加入一个可以手动停止的功能吧
要实现可以停止计时器,我们只需要拿到计时器的ID就可以了。
好,说干就干
function customInterval(callback, time) {
let timerId; // 用于存储计时器ID
function execute() {
callback(); // 执行回调函数
timerId = setTimeout(execute, time); // 设置下一次调用
}
timerId = setTimeout(execute, time); // 初始化定时器
// 返回一个对象用于控制定时器
return {
clear: () => clearTimeout(timerId),
};
}
// 使用示例
const interval = customInterval(() => {
console.log("Task executed");
}, 1000);
// 5秒后停止定时器
setTimeout(() => {
interval.clear();
console.log("Interval stopped");
}, 5000);
**我们在一开始设置了一个变量用来储存计时器的id,然后在函数的结尾返回了一个控制定时器的变量函数。当我们要停止计时器时,我们只需要调用它就可以了。
欧克了!是不是感觉大厂面试题也就这样!
稳了 稳了 稳了