JS定时器,你所要了解的那点事

背景:

开发过程中我们常常要用到定时器去完成某些需求。js为我们准备了两个函数:setTimeout和setInterval,我们在进入主题之前,先简单介绍一下它们

首先,它们都会返回一个整数编号用来表示定时器。将这个值传给各自的clear方法可以取消定时。

其次,setTimeout是期望推迟(delay)ms后执行函数, setInterval则是期望间隔(delay)ms就执行一次函数。

为什么只是说期望那?上一个🌰瞧瞧

先预测一下结果再运行代码,结果如下:

跟你想象中的结果一样吗?你会发现setTimeout并不是像它期望的那样—-延迟1s就执行,而是要等待bulky()执行结束后才执行,这就是定时器不定时的情形。

定时器是怎么实现定时的?为什么会出现不定时的情况?

首先,要明确的一点:javascript是以单线程的方式运行的。JavaScript的主要用途是与用户互动,以及操作DOM。若以多线程的方式,则可能出现冲突。假设有两个线程同时操作一个DOM元素,线程1要求浏览器删除DOM,而线程2却要求修改DOM样式,这时浏览器就无法决定采用哪个线程的操作。当然,我们可以为浏览器引入“锁”的机制来解决这些冲突,但大大提高复杂性,所以 JavaScript从诞生开始就选择了单线程执行。在某一时刻内只能执行特定的一个任务,并且会阻塞其它任务执行。

但是JavaScript 有个基于“Event Loop”并发的模型(不是并行)。前者是逻辑上的同时发生,而后者是物理上的同时发生。所以,单核处理器也能实现并发。

上图说明一下并发和并行:

再上图说明一下Event Loop

js既然是单线程的,也就意味着所有任务需要排队。所有任务可以分成两种,一种是同步任务(synchronous),另一种是异步任务(asynchronous)

  • 同步任务指的是,在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务,形成了一个执行栈(execution context stack)
  • 异步任务指的是,不进入主线程,而进入”任务队列”(task queue)的任务。”任务队列”是一个事件的队列(可以当作消息的队列来理解)。IO设备完成一项任务or异步任务有了运行结果,就在”任务队列”中添加一个事件,表示相关的操作可以进入”执行栈”,就等着执行栈调用了。

参照Event Loop的图,说一下大致的流程—-> 执行栈中流式执行函数(同步任务),可能会调用API在任务队列中加入事件(onlick,onload等等)但并不执行。只有当前执行栈没有其他操作时,任务队列才会入执行栈中,执行

原理讲完了,回到正题。因为setTimeout, setInterval是异步任务,调用之后不会直接进入执行栈,而是进入任务队列,所以只有等到当前执行栈没有其他操作,它们才会进入执行栈中执行, 以上就是为什么定时器不总是定时的原因了。

哦,对了如果delay时间周期设为0,相当于一个插队操作

举例

🌰献上:

运行结果

好了,以上内容就是我对js定时器的认识,希望可以帮助到你

未经本人允许,不得转载。文章有疏漏浅薄之处,请各位大神斧正

1 收藏 评论

相关文章

可能感兴趣的话题



直接登录
跳到底部
返回顶部