JavaScript 中的事件循环是什么?
让我们从不同的角度来研究一下 JavaScript 事件循环。听起来很有趣,对吧?确实如此!所以,坐稳,让我们深入研究一下!
事件循环的概念非常简单。但为了理解它,首先我们需要明确一些与事件循环相关的概念。
浏览器内部包含一个 JavaScript 引擎(我们考虑使用 Chrome 的V8 引擎)和一个可以正常运行 JavaScript 的环境。JavaScript 引擎分为两部分:堆 (Heap)和调用栈 ( Call Stack )。此外,引擎还包含一些名为Web API和回调队列 (Callback Queue)的辅助工具。
堆
它是一个非结构化的内存块。我们的代码的内存分配就在这里进行。作为程序员,我们不必太担心堆。
调用堆栈
我们可以将调用栈想象成一个厨房,所有代码都在这里执行或烹饪。每当我们尝试运行一段代码时,它都会首先进入调用栈,然后执行。它遵循后进先出(LIFO)的原则。即后进先出。
const lunch = () => console.log("It's time for lunch!");
const dinner = () => console.log("It's time for dinner!");
const breakfast = () => {
console.log("Time to breakfast!");
setTimeout(lunch, 3000);
dinner();
};
breakfast();
如果我们运行上面的代码,全局执行上下文main()将在浏览器上运行,JS 引擎将从第一行开始读取代码并搜索任务。在最后一行,调用了一个函数。因此,该函数将进入调用堆栈并执行任务。首先,它将打印Time to breakfast!,然后进入下一行,其中有一个异步代码块。
众所周知,JavaScript 是同步和单线程语言,这个异步代码块进入调用堆栈并突然弹出。这里 JS 引擎从它的助手Web API那里获得了帮助。 setTimeout() 在 Web API 上等待,在其计时器用完后(在本例中为 3 秒),3 秒后,回调函数进入回调队列并等待调用堆栈释放。此时,调用堆栈运行另一段代码。打印It's time for dinner!
Web API
Web API 充当 JS 引擎的助手。当 JS 引擎需要处理异步代码时,它会借助 Web API。Web API 负责处理 JavaScript 代码的阻塞行为。
在本例中,从上面的代码可以看出,Web API 将获取回调函数setTimeout(lunch, 3000);
,运行其计时器,并在 3 秒后将其传递给回调队列。
回调队列
它就像一个守卫,负责监视刚刚完成等待任务并进入 Web API 大门的异步回调函数堆栈。回调队列采用FIFO(先进先出)的机制。现在,它们在这里等待返回调用栈。但是调用栈如何知道回调队列中还有回调函数在等待呢? 这时,明星——事件循环出现了!
事件循环
事件循环就像一个守护者,负责与调用栈和回调队列保持良好的沟通。它会检查调用栈是否空闲,然后通知回调队列。之后,回调队列会将回调函数传递给调用栈执行。当所有回调函数都执行完毕后,调用栈就会退出,全局执行上下文也就释放了。
瞧!一点也不复杂!😄
感谢阅读。