什么是事件循环?为什么需要事件循环?
原因是 JavaScript 引擎并不是独立运行的,它是运行在宿主环境中,常用的也就是 Web 浏览器。所有这些环境都有一个共同“点”,即它们都提供了一种机制来处理程序中多个块的执行,且执行每块时调用 JavaScript 引擎,这种机制被称为 事件循环。
也就是 JavaScript 引擎本身没有时间的概念,只是一个按需执行 JavaScript 任意代码的片段环境。“事件”(JavaScript 代码执行)调度总是由包含它的环境进行。
// 伪代码
// eventLoop 是一个用来作队列的数组
var eventLoop = []
var event = null;
while(true) {
// 一次 tick
if (eventLoop.length > 0) {
event = eventLoop.shift();
try {
event();
}
catch (err) {
reportError(err);
}
}
}
在一个 while 循环实现的持续运行的循环中,循环每一轮称为 tick。对每一个 tick 来说,如果有事件在队列中等待,那么就会从队列中取一个事件出来执行。这些事件就是我们的回调函数。
需要注意的是,setTimeout 并没有直接把回调函数挂到事件循环的队列中,它做的是设定一个定时器,当定时器时间到了之后,环境会把我们的回调函数放到事件循环中,在未来执行的某个 tick 中取出并执行。
也就是说,程序分成了很多个小块,在事件循环队列中一个接一个地执行。严格地说,和我们程序不直接相关的其他事件也可能会插入到队列中。