简体   繁体   English

Node.js 中的事件循环

[英]Event loop in Node.js

We all know that in Node.js, the functions are handled by worker thread for execution and then send to the event queue and then the event loop looks into the call stack.我们都知道,在 Node.js 中,函数由工作线程处理执行,然后发送到事件队列,然后事件循环查看调用堆栈。 If the call stack is empty then the event loop takes the function's context environment to call stack, and then call stack process it and give it as a response.如果调用堆栈为空,则事件循环将函数的上下文环境用于调用堆栈,然后调用堆栈对其进行处理并将其作为响应。

My question is if we have multiple functions with same timeout function and then all the function is given to worker thread then worker thread sends their context environment to the event queue, and if the timeout of all the functions are same then they all come into the event queue at the same time and then if the call stack is empty then the event loop will send all the functions to call stack, and we all know the property of stack is FILO.我的问题是,如果我们有多个具有相同超时函数的函数,然后将所有函数都交给工作线程,然后工作线程将它们的上下文环境发送到事件队列,如果所有函数的超时都相同,那么它们都进入事件队列同时,如果调用栈为空,则事件循环会将所有的函数都发送到调用栈中,我们都知道栈的属性是FILO。

so if this happened resulting the last function should be sent in response first but this is not happening the first function is coming in response first if all the timeouts are the same?因此,如果发生这种情况,则应首先发送最后一个函数作为响应,但如果所有超时都相同,则第一个函数将首先响应?

There are lots of things wrong in how you describe things in your question, but I'll speak to the timeout issue that you ask about.您在问题中描述事物的方式有很多错误,但我会谈谈您提出的超时问题。

nodejs has its own timer system. nodejs 有自己的计时器系统。 It keeps a sorted list of timers and the ONLY Javascript timeout that has a physical system timer is the next one to fire.它保留了一个排序的计时器列表,并且唯一具有物理系统计时器的 Javascript 超时是下一个要触发的。 If multiple Javascript timeouts are set to fire at the same point in time, then they all share that one OS timer.如果多个 Javascript 超时设置为在同一时间点触发,则它们都共享一个操作系统计时器。

When that OS timer fires and when the main JS thread is free and able to pull the next event from the event loop, it will see a JS timer is ready to call its callback.当该操作系统计时器触发并且主 JS 线程空闲并且能够从事件循环中提取下一个事件时,它将看到一个 JS 计时器已准备好调用其回调。 If there are more than one ready to go, all for the same time, then the interpreter will call each of their callbacks one after the other, in the order the timers were configured (FIFO).如果有多个准备就绪,并且所有时间都在同一时间,那么解释器将按照定时器的配置顺序(FIFO)一个接一个地调用它们的每个回调。

We all know that in Node.js, the functions are handled by worker thread for execution and then send to the event queue and then the event loop looks into the call stack.我们都知道,在 Node.js 中,函数由工作线程处理执行,然后发送到事件队列,然后事件循环查看调用堆栈。 If the call stack is empty then the event loop takes the function's context environment to call stack, and then call stack process it and give it as a response.如果调用堆栈为空,则事件循环将函数的上下文环境用于调用堆栈,然后调用堆栈对其进行处理并将其作为响应。

My question is if we have multiple functions with same timeout function and then all the function is given to worker thread我的问题是,如果我们有多个具有相同超时函数的函数,然后将所有函数都提供给工作线程

That part is wrong.那部分是错误的。 They aren't given to a worker thread.它们不会提供给工作线程。

Then worker thread sends their context environment to the event queue, and if the timeout of all the functions are same then they all come into the event queue at the same time然后工作线程将它们的上下文环境发送到事件队列,如果所有函数的超时时间都相同,则它们都同时进入事件队列

As I described above, timers are a special type of event in the event loop code.如上所述,计时器是事件循环代码中的一种特殊类型的事件。 They use only one system timer at a time to schedule the next timer to fire.他们一次只使用一个系统计时器来安排下一个计时器触发。 Multiple timers set to fire at the same time are all stored in the same list (a list element for that particular time) and all share the same OS timer when it's their turn to be next.设置为同时触发的多个计时器都存储在同一个列表(该特定时间的列表元素)中,并且在轮到下一个时共享同一个操作系统计时器。 So, they don't all come into the event queue at the same time.因此,它们不会同时进入事件队列。 Nodejs has set one system timer for the group of timers set to fire at the same time. Nodejs 为设置为同时触发的一组计时器设置了一个系统计时器。 When that system timer fires and when the interpreter is free to pull the next event from the event loop, then it will call each callback for each timer set for that time one after another in FIFO order.当该系统计时器触发并且解释器可以自由地从事件循环中提取下一个事件时,它将以 FIFO 顺序为该时间设置的每个计时器依次调用每个回调。

and then if the call stack is empty then the event loop will send all the functions to call stack, and we all know the property of stack is FILO.然后如果调用栈为空则事件循环会将所有函数发送到调用栈,我们都知道栈的属性是FILO。

I don't know what "send all the functions to that call stack" means.我不知道“将所有函数发送到该调用堆栈”是什么意思。 That's not how things work at all.事情根本不是这样的。 node.js runs your Javascript in a single thread (except for WorkerThreads which are not in play here) so it calls the callback for one timer, runs that to completion, then calls the callback for the next timer, runs it to completion and so on... node.js 在单个线程中运行您的 Javascript(除了 WorkerThreads 不在此处运行),因此它会调用一个计时器的回调,将其运行到完成,然后调用下一个计时器的回调,将其运行到完成等等在...

so if this happened resulting the last function should be sent in response first but this is not happening the first function is coming in response first if all the timeouts are the same?因此,如果发生这种情况,则应首先发送最后一个函数作为响应,但如果所有超时都相同,则第一个函数将首先响应?

As I've said a couple times above, multiple timers set to fire at the same use one system timer and when that system timer fires, the callbacks for each of those timers are called one after the other in FIFO order.正如我在上面多次说过的,多个定时器设置为同时触发,使用一个系统定时器,当该系统定时器触发时,每个定时器的回调按 FIFO 顺序依次调用。


References参考

You can learn more about the node.js timer architecture here: How does Node.js manage timers .您可以在此处了解有关 node.js 计时器架构的更多信息: Node.js 如何管理计时器

And, here's some more info about the node.js timer architecture taken from comments in the source code: How many concurrent setTimeouts before performance issues?而且,这里有一些关于 node.js 计时器架构的更多信息来自源代码中的评论:在性能问题之前有多少并发 setTimeouts? . .

Looking for a solution between setting lots of timers or using a scheduled task queue 在设置大量计时器或使用计划任务队列之间寻找解决方案

Six Part Series on the Node.js Event Loop and How It Works Node.js 事件循环及其工作原理的六部分系列

My question is if we have multiple functions with same timeout function我的问题是我们是否有多个具有相同超时功能的功能

poll phase controll the timer轮询阶段控制定时器

First read here 首先阅读这里

I highly recommend this series 我强烈推荐这个系列

So the main question is how does Node decide what code to run next?所以主要的问题是 Node 如何决定接下来运行什么代码?

As we know the Event Loop and the Worker Pool maintain queues for pending events and pending tasks, respectively.正如我们所知,事件循环和工作池分别维护待处理事件和待处理任务的队列。

don't confuse with Worker thread不要与 Worker 线程混淆


Worker threads is different concept Read here工作线程是不同的概念阅读这里

But In realtiy the Event Loop does not actually maintain a queue.但实际上,事件循环实际上并不维护队列。 Instead, it has a collection of file descriptors that it asks the operating system to monitor, using a mechanism like epoll (Linux), kqueue (OSX), event ports (Solaris), or IOCP (Windows).相反,它有一组文件描述符,它要求操作系统使用 epoll (Linux)、kqueue (OSX)、事件端口 (Solaris) 或 IOCP (Windows) 等机制进行监视。 These file descriptors correspond to network sockets, any files it is watching, and so on.这些文件描述符对应于网络套接字、它正在监视的任何文件等。 When the operating system says that one of these file descriptors is ready, the Event Loop translates it to the appropriate event and invokes the callback(s) associated with that event当操作系统说这些文件描述符之一已准备好时,事件循环将其转换为适当的事件并调用与该事件关联的回调

The Worker Pool uses a real queue whose entries are tasks to be processed. Worker Pool 使用一个真正的队列,其条目是要处理的任务。 A Worker pops a task from this queue and works on it, and when finished the Worker raises an "At least one task is finished" event for the Event Loop.一个 Worker 从这个队列中弹出一个任务并对其进行处理,当完成时,该 Worker 为事件循环引发“至少一个任务已完成”事件。

timer callback is called depends on the performance of the system (Node has to check the timer for expiration once before executing the callback, which takes some CPU time) as well as currently running processes in the event loop.定时器回调的调用取决于系统的性能(节点必须在执行回调之前检查定时器是否过期,这需要一些 CPU 时间)以及事件循环中当前正在运行的进程。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM