首页 > 其他分享 >面试考题:定时器底层逻辑

面试考题:定时器底层逻辑

时间:2024-12-06 19:04:56浏览次数:4  
标签:执行 定时器 console log setInterval 面试 考题 setTimeout

前言

让我们回想一下关于定时器的内容,我们只知道,他是在我们设置的时间后才异步执行的程序。

可在面试时回答这个就够了吗?那当然是不够的。

本文将带你深入了解定时器底层

定义

我们先了解什么是定时器。

在JavaScript 中,定时器是一种用于延迟执行代码或定期执行代码的机制。它们允许开发者控制代码执行的时间点,从而实现诸如动画、轮询服务器、设置等待时间等功能。而定时器也分为两类setTimeoutsetInterval

执行原理

那么定时器的执行原理是什么呢?

我们都知道,JavaScript是单线程,只有一条主线程来处理任务,而我们的定时器则是可以异步执行的,在主线程任务结束后,才轮到我们的定时器执行。执行的都是我们的回调函数,放入处理异步函数的核心机制Event loop(事件循环)中,决定了什么时候执行代码。

总的来说,就是当程序碰到定时器时,会将其放入事件循环中,先忽略掉,待主线程内其他任务完成时,再执行定时器任务。

setTimeout

setTimeout 是 JavaScript 中用于延迟执行代码的内置函数。它允许你指定一段代码(通常是一个函数)在经过给定的时间间隔后执行。这个时间间隔是以毫秒为单位的,1000 毫秒等于 1 秒。也是最常见的定时器用法。

例子有:

        const timeout= setTimeout(function(){
            console.log('abcdefg');
        },10000)
        console.log(123)

先输出123,之后等待十秒钟左右,才会进行定时器输出。

最小时间

假如我将延迟设置为0ms,那么定时器会立即执行吗?

答案是否定的。定时器并不会立即执行

依旧是先输出123

不对啊,我把延迟时间设置为0,按道理来说不应该是按照文档流,从上到下依次执行吗?怎么先输出的还是123呢?

有两个方面:

  1. 在定时器运行的时候,浏览器有一个延迟时间的最小值,为4ms。意味着即使你把延迟时间设置为0,实际的延迟也会有4ms。而在node环境中,延迟为1ms。

  2. 前面提到了,定时器是一个异步执行的程序。必须在主线程程序执行完毕后,才轮到了异步执行。所以这里先运行了主程序的输出console.log(123),随后才运行了我们的定时器,所以123才会先输出。运行也有一个主次之分。

定时器一定会运行吗?

这我们又可以衍生到另一个问题。

是不是在我们的延迟时间到了后,一定会执行我们的定时器函数呢??

答案也是否定的。

       const timeout= setTimeout(function(){
            console.log('abcdefg');
        },0)
        while(true){   // 死循环
            
        }
        console.log('123')

此时我们的页面会一直处于加载状态。

前面也说了,JavaScript是单线程的,如果主线程上的程序任务运行时间超过了延迟时间

或主线程任务陷入死循环等情况。

在JavaScript中,所有程序在运行时都在同一个调用栈上按顺序执行。而定时器就排在主程序后面。如果主程序一直没有运行完毕,那么永远也轮不到定时器执行。所以并不是到了延迟时间后就会执行。

setInterval

这是定时器的另一个类型。他会在每次延迟时间后重复的运行定时器函数

 const interval= setInterval(function(){
            console.log('abcdefg');
        },1000)

        console.log('123')

此时我们会得到

左边的40就是他的运行次数。

那么是不是一直执行有些妨碍我们的任务。那我们怎么停止他呢?

<body>
    <button id= "btn"> 关闭计时器 </button>
    <script>
        const btn = document.getElementById('btn')

       btn.addEventListener('click',function(){
       clearInterval(interval)
})

          const interval=setInterval(function(){
         console.log('qa');
        },1000)
console.log(123)
    </script>
</body>

 

一般我们用clearIntervalclearTimeout来结束我们的定时器。这里我们还借用了按钮,可以看到我们的执行效果后再关闭定时器。一般都是返回我们的定时器ID。

我们还可以用setTimeout来结束setInterval

let intervalId = setInterval(() => {
console.log('This is a periodic message'); 
}, 1000);
// 使用 setTimeout 在 5 秒后停止 setInterval
setTimeout(() => {
console.log('Stopping the interval after 5 seconds...');
clearInterval(intervalId);
console.log('Interval has been cleared.');
}, 5000);

手搓定时器

但在面试的时候,面试官可能会要求我们用setTimeout来实现setInterval的重复运行效果。 那我们应该怎么做呢?

首先我们应该想的的是:递归。 一直调用自己,不就是重复运行的效果吗?怎么才能实现呢?

先给源码:

function customSetInterval (fn,time){
      let intervalid =null;
       function loop(){
       // 递归循环,类似setInterval
        intervalid = setTimeout(()=>{
            fn();
            loop();
        },time)
      }
      loop();
      // 清理定时器
      return () => clearTimeout(intervalId)
    }
     const interval = customSetInterval(function(){
        console.log('手搓定时器')
    },1000)

我们得到效果:

完美实现了setInterval的效果。

首先定义一个变量 intervalid,用于保存 setTimeout 返回的定时器 ID。

使用 setTimeout 设置一个延迟执行的回调函数。

每次回调函数执行时,都会调用传入的 fn 函数,并在 fn 执行完毕后再次调用 loop

从而形成一个循环,类似于 setInterval 的周期性调用。

然后用clearTimeout来清理定时器

然后就是使用实例了,每隔一秒生成一个手搓定时器。 如果想停止,只需要用setTimeout停止。在五秒后停止生成

    setTimeout(()=>{
        interval()
    },5000)

在复习一下前面,此时也只生成了4次而不是5次。

是因为主程序运行也花费了一些时间,生成5次的时间不够。

结语

这就是定时器的底层运行,这样回答。面试官包给满分。

原文:https://juejin.cn/post/7444736409069453346

标签:执行,定时器,console,log,setInterval,面试,考题,setTimeout
From: https://blog.csdn.net/gaotlantis/article/details/144272542

相关文章

  • 关于redis的面试题
    目录一:redis的基础知识二:Redis协议与异步方式三:Redis的存储原理和数据模型四:Redis的持久化和高可用性一:redis的基础知识1:redis是一个内存数据库,KV数据库。2:包含的数据结构:string,list,hash,set,zset,其中string是一个安全的二进制字符串,我们可以在这个字符串的末尾添加'\0......
  • Java 2025年面试总结(持续更新)
    1.自我介绍简单一点吧,把自己的情况说清楚,一两分钟即可。2.微服务的组件答:微服务是把一个类似单体项目根据某种维度进行拆分,比如根据功能模块进行拆分。拆分之后,具备了更好的抗压性/扩展性,还可以更好的解耦,但是维护相比之前会更麻烦了常用的组件有SpringCloud。其中里面......
  • 已入职华为大模型算法岗,面试真的很水的…
    觉得中大厂面试太难的,完全就是自己没准备充分,技术不到位,没准备的面试完全是浪费时间,更是对自己的不负责!今天我给大家分享一下我整理的大模型面试专题和答案,其中大部分都是面试常问的面试题,可以对照这查漏补缺奥!祝大家早日上岸呀!方向:大模型算法工程师整个面试持续了1小......
  • 面试官:如何在 JavaScript 中选择最合适的函数定义方式?
    在最近的一个Chrome插件项目中,我深入探索了JavaScript中不同的函数定义方式。随着开发的深入,我发现理解这些方式的优劣势至关重要。比如,当我使用函数声明和箭头函数时,遇到了一些作用域和this指向的问题,这让我很困惑。此外,我还注意到,立即执行函数在某些情况下能够避免全局污......
  • 翻到了我2016年的面试经历,那是一个互联网的黄金时代。
    你好呀,我是歪歪。最近在整理便签的时候,看到了我2016年刚刚大学毕业,去北京面试记录的面试过程。当时记录的还挺详细的,一字不改,准备分享出来给大家看看8年前的面试题,看看属于Java开发甚至是整个计算机行业的黄金时代。我是2016年6月底毕业,7月20日去的北京。那个时......
  • 前端面试题(20241205)
    1.Vue如何检测数组变化1.方法重写(push、pop、shift、unshift、splice、sort和reverse)。2.使用Vue.set或vm.$set(对于直接通过索引设置数组项的操作例如arr[index]=newValue)。3.数组长度变化。4.响应式转换。2.Vue的父子组件生命周期钩子函数执行顺序父组件先初......
  • JavaScript定时器
    1.setInterval(functiontime)周期定时器vari=0setInterval(function(){console.log(i++)},3000)//3000指的是3000毫秒也就是3s//这个事件会每隔三秒显示一个i每次i++2.setTimeout延迟定时器setTimeout(function(){console.log(i++)},3000)//这个是打......
  • 前端面试题
    JavaScript基础知识:1、数据类型基础数据类型:NumberStringBooleanNullUndefinedSymbolBigInt引用数据类型:ObjectArrayFunctionDate2、作用域与闭包作用域:变量的可访问范围。分为全局作用域、函数作用域、块级作用域(let和const)。闭包:函数可以“记住”并访问定义......
  • 全网最全JAVA面试八股文,终于整理完了
    前言又到一年金三银四面试跳槽季,你准备好了吗?今天为大家整理了目前互联网出现率最高的大厂面试题,所谓八股文也就是指文章的八个部分,文体有固定格式:由破题、承题、起讲、入题、起股、中股、后股、束股八部分组成,题目一律出自四书五经中的原文。而JAVA面试八股文也就是为了考......
  • 10万字208道Java经典面试题总结(附答案)
    1、JDK和JRE有什么区别?JDK(JavaDevelopmentKit),Java开发工具包JRE(JavaRuntime Environment),Java运行环境JDK中包含JRE,JDK中有一个名为jre的目录,里面包含两个文件夹bin和lib,bin就是JVM,lib就是JVM工作所需要的类库。2、==和 equals 的区别是什么?对于基本类型,==比较的......