setTimeout 放入消息队列的时机

1,283 阅读2分钟

前言

由同学工作中引发的一个问题牵涉出的疑问: 在遇到 setTimeout 代码的时候就立即放入任务队列等到定时时间到了再执行回调 还是 等到定时结束后再将回调放入任务队列。

正文

这个问题涉及到 js 中的宏任务概念,还有 V8 引擎的消息队列

从上面的资料里可以知道:当定时时间到了后,才会将 setTimeout 的回调函数放入消息队列中,但是具体执行的时机并不只是由定时时间决定的,还取决于当前的执行栈、当前 event loop 的事件执行时间,所以定时时间相当于一个起步时间。

至于是如何记住各个 setTimeout 的定时时间,并在定时过后放入消息队列的,据我所知定时器调度策略比较复杂,会有专门的调度策略在合适的时间添加对应的回调任务,我个人也偏向于异步处理模块对此做了处理。但是在日常开发中,不建议去揣测底层的运行机制会出现怎样的结果,因为 setTimeout 的执行时间是个变量,我们知道它的起步时间,但无法知道具体的执行时间,所以为了保证代码逻辑的可靠性,不要堆砌各种定时函数,尽量使用 promise 或者 async 等异步函数去保证代码的执行顺序。

后话

参考资料:

微任务、宏任务与Event-Loop

以小见大——从setTimeout引申JS的几大特性

V8引擎详解(八)——消息队列

PS:在搜索这道题目的时候,发现了一篇搞定(Js异步、事件循环与消息队列、微任务与宏任务),描述了宏任务微任务之间的不同结合执行顺序,看完之后克服了我之前面试的时候遇到类似题目的恐惧,如果有需要的小伙伴可以去看一看题目。

如果有什么错误,欢迎指正~