Event Loop
1. 参考资料
2. 整理
其中第二篇资料这一次,彻底弄懂 JavaScript 执行机制,更具有说服力,能解释一部分的异步情况。
2.1.1 知识点
js代码在执行时会将不同变量存放于内存中的不同位置,堆(heap)和栈(stack),其中堆存放着一些对象,栈存放一些基础类型变量以及对象的指针。
执行栈 => 存放同步代码。 事件队列 => 存放异步代码。
当异步事件返回结果(比如定时器时间到期,ajax请求返回完数据)时,js会将异步事件的回调添加到事件队列中。而后在执行栈已经执行完毕情况之后,会查看事件队列是否有任务,如果有任务,则将任务放到执行栈中进行调用。
异步任务分为微任务(micro task)与宏任务(macro task),对应会有微任务事件队列与宏任务事件队列: 宏任务:
微任务:
当前执行栈执行完毕时会立刻处理所有微任务队列中的事件,然后再去宏任务队列取出一个事件,同一次事件循环中,微任务永远在宏任务之前执行
2.1.2 说明
文章后续还提到了 node
中 libuv
的事件循环模型,以及事件循环各个阶段的解释。
2.2.1 知识点
同步和异步任务进入不同的执行"场所",同步任务进入主线程执行栈,异步任务进入
Event Table
并注册回调函数当异步任务指定的事件完成(定时器到时,请求
success
)时,Event Table
会把回调函数转移到事件队列
(Event Queue)当主线程执行栈的任务执行完毕,会去事件队列读取函数,进入主线程执行
上述过程不断重复,形成事件循环
setTimeout: 即执行到该代码时,会进入Event Table
注册回调函数,当定时器到时之后,Event Table
会将回调函数转移到事件队列
。
setInterval: 即执行到该代码时,会进入Event Table
注册回调函数,之后每隔指定的时间,Event Table
会将回调函数转移到事件队列
。
除了广义上的同步任务和异步任务,还会将任务划分为宏任务和微任务:
macro-task(宏任务):包括整体代码script,setTimeout,setInterval
micro-task(微任务):Promise,process.nextTick
这个宏任务的划分比2.1资料中的划分多了一个整体代码script
2.2.2 说明
这篇文章举例了一些异步代码的例子,便于理解。同时全文表达出 [执行一个宏任务,执行当前所有微任务]为一个 event-loop
。
2.3 Event Loop的规范和实现
2.3.1 知识点
process.nextTick 注册的函数优先级高于 Promise, 即微任务从 Event Table 转移到事件队列并不完全根据代码中出现的顺序,还会有优先级的区别。
在评论区中发现以下说法:
process.nextTick 是放到当前同步执行栈的尾部,是一定比异步的任务队列早的。并不是因为优先级高于其他异步的任务。同步的执行栈到异步任务队列,process.nextTick 就是处于中间的那个。 当然异步下,任务队列里就分宏任务 / 微任务。但是我也觉得这里不是由优先级决定的,而是宏任务内的执行栈清空后,再清空当前宏任务内的微任务。接着以此循环再去清空下一个宏任务的执行栈,再清空微任务。
这个说法就相当于说,process.nextTick
是在同步执行栈尾部,在执行异步任务队列之前的。就是说它是一个在所有其它异步任务之前的异步任务。(有空再翻资料)
即process.nextTick这段代码不管是在位置1还是位置2,输出结果都是1,7,6,8,2,4,3,5
同时以下这段代码的返回结果是不确定的:
有可能返回1,7,6,8,2,4,3,5,9,11,10,12
,但也可能返回1、7、6、8、2、4、9、11、3、10、5、12
,即两个setTimeout的执行可能混合。
原因在于:
这两段 setTimeout
都没有指定 timeout
时间,默认是0,延时相同,被合并进同一个expired timers queue
而一起执行。
当做合并为同一个宏任务?,那为啥还会有两种可能的结果?一直返回
1、7、6、8、2、4、9、11、3、10、5、12
才对吧,这一块还没有理解
2.3.2 说明
这篇文章是在阅读 2.2这一次,彻底弄懂 JavaScript 执行机制之后写的,因此很适合和 2.2
连着一起看,同时还翻阅了 blink
与 node
的源码解释了定时器0ms和1ms为什么效果是一致的
,很具说服力。
2.4 代码解析
示例一
以上这段代码最终打印clock1, clock3, clock2
.
针对这种嵌套调用的情况,可以根据这一次,彻底弄懂 JavaScript 执行机制去理解:
示例二
以上这段代码始终打印clock1, clock2, clock3
Last updated