NodeJS 中的事件循环——同步和异步代码初学者指南

萌够才回家 2021-08-31 10:20:33 浏览数 (2433)
反馈

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 如何逐行执行程序。

当我们阅读本节时,您将开始了解您在此处看到的内容:1

在左上角,您有一个要执行的 Node 文件。在左下角,您有一个程序的输出终端。然后你有调用堆栈、节点 API 和回调队列。所有这些共同构成了 NodeJS 环境。

对于同步编程,您只需要关注调用堆栈。这是 NodeJS 环境中唯一可以在这种情况下工作的部分。

回调堆栈是一种数据结构,用于跟踪将在程序内部运行的所有函数的执行情况。这种数据结构只有一个开放端来添加或删除顶级项目。

当程序开始执行时,它首先被包裹在一个匿名main()函数中。这是由 NodeJS 自动定义的。所以main()首先被推送到回调堆栈。

2

接下来,创建变量a和b并将它们的总和存储在变量中sum。所有这些值都存储在内存中。

现在,这console.log()是一个被调用并推送到回调堆栈中的函数。它被执行,你可以在终端屏幕上看到输出。

3

执行此函数后,它将从回调堆栈中删除。然后main()也被删除,因为程序中没有任何东西可以调用。这就是同步程序的执行方式。

45

现在,让我们看看异步函数或程序如何在 NodeJS 中执行。我们需要回调堆栈、Node API 和回调队列一起来处理异步函数。

让我们从这个例子开始:

1-1

像往常一样,当程序开始执行时,首先将main()函数添加到回调堆栈中。然后console.log("Start")被调用并添加到回调堆栈中。处理后,输出在终端上可见,然后从回调堆栈中删除。

2-13-1

现在下一个是setTimeOut(...Zero...)添加到回调堆栈中的函数。

由于这是一个异步函数,它不会在回调堆栈中得到处理。然后它从回调堆栈添加到节点 API,在那里注册事件并设置回调函数以在后台处理。

4-15-1

接下来是setTimeOut(...Two..)从回调堆栈添加到 Node API 的 ,因为它是一个异步函数。然后另一个回调函数被设置为在后台超时 2 秒后处理。到此为止,可以执行其他功能。

这被称为非阻塞行为,所有同步函数首先被处理和执行,异步函数在后台处理,同时等待轮到它们被执行。

67

接下来,该console.log("End")函数最后在回调堆栈中被调用并在此处进行处理。您可以在终端上看到输出。现在,所有同步函数都被处理,并main()从回调堆栈中删除。

在后台,所有异步函数都得到处理,它们的回调存储在回调队列中。首先处理的将首先添加到队列中以在回调堆栈中执行。

8910

注意:异步函数不能在回调堆栈内运行,直到它被清空。这意味着main()从调用堆栈中删除后,所有异步函数才能开始执行。

现在,使用事件循环将它们一一推送到回调堆栈并最终执行。每个回调函数将打印console.log()每次调用该函数的值。

11

最后,这些在执行后也被删除,现在回调堆栈为空。

12

这就是 NodeJS 如何在环境中执行同步和异步函数,以及事件循环如何调用异步函数。

结论

在本文中,您了解了 NodeJS 的内部工作原理,并了解了异步程序是如何执行的。

现在您应该明白为什么两秒延迟函数不会阻止程序的其余部分执行。您也知道为什么零秒延迟函数在“End”打印后最后打印该值。

就这样!我希望你喜欢阅读这篇文章并学到一些新东西。如果您觉得这篇文章有用,请分享它。


0 人点赞