大厂真题!前端面试手写代码——使用 setTimeout 实现 setInterval

787 阅读4分钟

如何用 setTimeout 实现 setInterval ?

这是前几天学校学长的一道大厂面试的手写场景编程题!

来跟上节奏!

让我们一起拿下这道大厂面试题!

image.png

首先 让我们先深入理解一下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这两个计时器之间有什么相同点和差别,再选择合适的算法实现它。

  1. 相同点:这两个计时器都是设置延时执行代码的函数,都是异步执行。
  2. 不同点:setTimeout是在指定时间之后执行一次,而setInterval则是反复执行某段代码.

那通过分析我们这里可以看到这两个计时器的功能差不多的,无非一个就执行一次而另一个执行多次。

嗯...那这里适合什么算法呢? 递归 我们这里可以使用递归setTimeout函数反复执行不就实现了setInterval了

让我们正式开始吧!

  1. 定义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,然后在函数的结尾返回了一个控制定时器的变量函数。当我们要停止计时器时,我们只需要调用它就可以了。

欧克了!是不是感觉大厂面试题也就这样!

稳了 稳了 稳了

image.png