什么是事件循环?
先通过一段伪代码了解一下这个概念 :
// eventLoop是一个用作队列的数组 //(先进,先出)var eventLoop = [ ];var event;//“永远”执行while (true) {// 一次tickif (eventLoop.length > 0) {// 拿到队列中的下一个事件event = eventLoop.shift();// 现在,执行下一个事件try {event();}catch (err) {reportError(err);}}}
可以看到,有一个用 while 循环实现的持续运行的循环,循环的每一轮称为一个 tick。 对每个 tick 而言,如果在队列中有等待事件,那么就会从队列中摘下一个事件并执行。这些事件就是你的回调函数。
一定要清楚,setTimeout(..) 并没有把回调函数挂在事件循环队列中。它所做的是设定一个定时器。当定时器到时后,环境会把你的回调函数放在事件循环中,这样,在未来某个时刻的 tick 会摘下并执行这个回调。
如果这时候事件循环中已经有 20 个项目了会怎样呢?回调就会等待。它得排在其他项目后面——通常没有抢占式的方式支持直接将其排到队首。这也解释了为什么 setTimeout(..) 定时器的精度可能不高。大体说来,只能确保回调函数不会在指定的时间间隔之前运行,但可能会在那个时刻运行,也可能在那之后运行,要根据事件队列的状态而定。所以换句话说就是,程序通常分成了很多小块,在事件循环队列中一个接一个地执行。严格地说,和程序不直接相关的其他事件也可能会插入到队列中。
