NodeJS 中的事件循环——同步和异步代码初学者指南
NodeJS 是一个异步事件驱动的 JavaScript 运行时环境,旨在构建可扩展的网络应用程序。这里的异步是指 JavaScript 中所有在后台处理而不阻塞任何其他请求的函数。在本文中,您将学习和理解 NodeJS 是如何工作的,以及如何以同步或异步方式处理发送到服务器的所有功能或请求。
什么是事件循环?
您可能已经猜对了——Node 在 NodeJS 环境中使用事件循环处理请求。但首先,让我们了解一些有助于我们理解整个机制的基本术语。
事件循环是一个事件监听器,它在 NodeJS 环境中运行,并随时准备监听、处理和输出事件。
事件可以是从鼠标单击到按键或超时的任何事件。
什么是同步和异步编程?
同步编程意味着代码按照它定义的顺序运行。在同步程序中,当一个函数被调用并返回了某个值时,才会执行下一行。
让我们用这个例子来理解:
const listItems = function(items) {
items.forEach(function(item) {
console.log(item)
})
}
const items = ["Buy milk", "Buy coffee"]
listItems(items)
The output will look like this:
"Buy milk"
"Buy coffee"
在这个例子中,当listItems(items)函数被调用时,它将循环遍历项目数组。console.log(item)首先为数组的第一项调用该函数并打印"Buy milk". 然后再次console.log(item)执行,这次它传递数组的第二项并打印"Buy coffee".
所以你可以说这个函数是按照它定义的顺序执行的。
另一方面,异步编程指的是不按顺序执行的代码。这些功能不是按照它们在程序中定义的顺序来执行的,而是仅在满足某些条件时才执行的。
例如,setTimeOut()在某个预定义的毫秒数延迟后执行任务。
setTimeOut(function(){
return( console.log("Hello World!") )
}, 3000)
这些函数不会逐行运行,而是仅在需要运行时才运行,而不管函数的声明如何。在这种情况下,当所有同步功能都执行完毕后,该功能会在 3 秒后自动运行。
注意:异步函数只有在所有同步函数都执行完后才会运行和执行。在此之前,它们将在后台处理。
如果想深入了解NodeJS和异步编程,可以参考这篇文章
但是,NodeJS 如何在后台处理异步函数并先运行所有同步函数?所有这些机制都可以用 NodeJS 事件循环轻松解释。
事件循环如何工作?
现在让我们看看 NodeJS 事件循环如何使用 Nodejs 事件循环图执行一个简单的同步程序。然后我们将检查 Node 如何逐行执行程序。
当我们阅读本节时,您将开始了解您在此处看到的内容:
在左上角,您有一个要执行的 Node 文件。在左下角,您有一个程序的输出终端。然后你有调用堆栈、节点 API 和回调队列。所有这些共同构成了 NodeJS 环境。
对于同步编程,您只需要关注调用堆栈。这是 NodeJS 环境中唯一可以在这种情况下工作的部分。
回调堆栈是一种数据结构,用于跟踪将在程序内部运行的所有函数的执行情况。这种数据结构只有一个开放端来添加或删除顶级项目。
当程序开始执行时,它首先被包裹在一个匿名main()函数中。这是由 NodeJS 自动定义的。所以main()首先被推送到回调堆栈。
接下来,创建变量a和b并将它们的总和存储在变量中sum。所有这些值都存储在内存中。
现在,这console.log()是一个被调用并推送到回调堆栈中的函数。它被执行,你可以在终端屏幕上看到输出。
执行此函数后,它将从回调堆栈中删除。然后main()也被删除,因为程序中没有任何东西可以调用。这就是同步程序的执行方式。
现在,让我们看看异步函数或程序如何在 NodeJS 中执行。我们需要回调堆栈、Node API 和回调队列一起来处理异步函数。
让我们从这个例子开始:
像往常一样,当程序开始执行时,首先将main()函数添加到回调堆栈中。然后console.log("Start")被调用并添加到回调堆栈中。处理后,输出在终端上可见,然后从回调堆栈中删除。
现在下一个是setTimeOut(...Zero...)添加到回调堆栈中的函数。
由于这是一个异步函数,它不会在回调堆栈中得到处理。然后它从回调堆栈添加到节点 API,在那里注册事件并设置回调函数以在后台处理。
接下来是setTimeOut(...Two..)从回调堆栈添加到 Node API 的 ,因为它是一个异步函数。然后另一个回调函数被设置为在后台超时 2 秒后处理。到此为止,可以执行其他功能。
这被称为非阻塞行为,所有同步函数首先被处理和执行,异步函数在后台处理,同时等待轮到它们被执行。
接下来,该console.log("End")函数最后在回调堆栈中被调用并在此处进行处理。您可以在终端上看到输出。现在,所有同步函数都被处理,并main()从回调堆栈中删除。
在后台,所有异步函数都得到处理,它们的回调存储在回调队列中。首先处理的将首先添加到队列中以在回调堆栈中执行。
注意:异步函数不能在回调堆栈内运行,直到它被清空。这意味着main()从调用堆栈中删除后,所有异步函数才能开始执行。
现在,使用事件循环将它们一一推送到回调堆栈并最终执行。每个回调函数将打印console.log()每次调用该函数的值。
最后,这些在执行后也被删除,现在回调堆栈为空。
这就是 NodeJS 如何在环境中执行同步和异步函数,以及事件循环如何调用异步函数。
结论
在本文中,您了解了 NodeJS 的内部工作原理,并了解了异步程序是如何执行的。
现在您应该明白为什么两秒延迟函数不会阻止程序的其余部分执行。您也知道为什么零秒延迟函数在“End”打印后最后打印该值。
就这样!我希望你喜欢阅读这篇文章并学到一些新东西。如果您觉得这篇文章有用,请分享它。