Node.js 非阻塞函数后的回调处理 returns
Node.js callback handling after nonblocking function returns
我正在阅读一本 Node.js 书,试图清楚地了解 Node.js 如何处理事件、异步函数及其回调、非阻塞 I/O 等。以下是我如何理解 事件循环 基础知识的简要概要,然后是我无法在书中找到明确答案的几个问题。如果我的基本理解有任何错误,请指正。那么问题就来了。
据我了解,Node.js 在单个线程上运行所有功能。这包括 事件循环 。换句话说,当 事件 发生时,例如HTTP 请求,该请求进入事件队列。事件循环本身一次从队列中拉出一个事件并对其进行整体处理。这可能意味着 return 立即得到一个简单的结果,或者在 I/O 到第三方(如数据库或文件系统)的情况下,进行非阻塞的异步调用,回调到告诉系统在异步功能完成时要做什么。同时,队列中的所有其他事件都在等待。如果开发人员编写的方法不异步卸载工作或向工作人员卸载,则在处理任务时整个服务器将挂起。
如果有任何错误,请澄清,因为这可能会影响我对以下问题答案的理解,我希望这些问题不会太愚蠢.
- 文件系统、数据库和其他此类调用不会阻塞,因为 Node.js 将它们卸载到异步调用,但是如果 Node.js 是单线程的,谁在监听新事件并管理事件循环?当 Node.js 正在处理一些事件时,谁在监听和管理新传入事件的队列,以便在 Node.js 的注意力在别处时它们不会丢失?我是否从根本上误解了它是如何工作的?除了作为 运行 我们的代码的引擎部分之外,是否有守护进程 运行 之类的东西来管理事件队列?
- 关于异步函数的回调的类似问题......谁在监听和管理传入的回调,而 Node.js 已经在处理一些回调或事件,这样回调就不会因为它的到来而丢失处理中?
- 当异步函数完成时,回调会中断事件循环并立即控制,还是异步函数的 return 在结束时作为新事件重新进入事件循环排队等待轮到自己了?换句话说,来自异步函数的回调是像任何其他事件一样对待,还是有所不同?如果区别对待,又如何呢?这是一个根本愚蠢的问题吗?
- 回调是否可以像写得不好的事件处理程序(例如 HTTP 请求处理程序)一样阻塞?换句话说,回调中包含的编写错误的代码会阻塞服务器吗? (我假设答案是肯定的,但想知道我是否正确。)
这是一个类似的问题,答案很好,但细微差别略有不同。 This linked question解决了用户代码的异步性问题,但其中一个答案似乎包含对我的问题的附带回答。我对用户从不与之交互的 Node 内部工作原理也很感兴趣,例如谁在 Node 阻塞时管理新的客户端请求插入事件队列,对于回调等也是如此。
Is NodeJS really Single-Threaded?
多方搜集,慢慢读。
Node.js 不完全是单线程的。它将磁盘、数据库、HTTP API 调用卸载到其他线程,一旦完成,它们就会在事件循环中排队。
- 还有其他线程参与。
- 事件循环应该是一个类似Queue的数据结构,被很多线程访问
- 大部分时间重新进入事件循环(在队列末尾)。但是有一些方法可以把它放在前面。 (需要检查)
- 是的。例如。如果您使用 fs.readFileSync,它会阻塞服务器一段时间。
事件循环:http://2014.jsconf.eu/speakers/philip-roberts-what-the-heck-is-the-event-loop-anyway.html
凭记忆写的。如果这对你有帮助,我可以尝试查找参考资料。
首先,从这个开始是有帮助的:
短语 "Node.js is single threaded" 有点误导,技术上也不正确。对于代码中的所有意图和目的,您的代码是单线程的,但 Node 本身不是。 Node 中有一些 API 和操作(通常它是异步的 I/O 执行此操作)将在内核或 LibUV 的线程池中使用不同的线程。
现在按每个问题的顺序分解:
- File system, database, and other such calls don't block because Node.js offloads them to asynchronous calls, but if Node.js is single threaded, who is listening for new events and managing the event loop? While Node.js is processing some event, who is listening and managing the queuing of new incoming events so they are not lost while Node.js's attention is elsewhere? Do I fundamentally misunderstand how this works? Is there like a daemon running or something, apart from the part of the engine that is running our code, that manages the event queue?
当 Node 正在处理一些事件时,没有人在监听队列。它们并没有丢失,因为它是一个 queue。它会等到 Node 完成它正在做的事情,这样它就可以 return 到队列中检查它是否有下一步要做的事情。这是 Node "event loop" 的一部分,为什么阻塞代码(永远不允许 Node return 到事件循环顶部的代码,或者需要很长时间才能这样做)是有问题的。
异步 I/O 操作在单独的线程中,可以在 Node 执行其他操作时将内容放入队列。当 Node 完成那件事后,它可以去处理队列上的事情。
- Similar question for asynchronous functions' callbacks ... who is listening for and managing incoming callbacks while Node.js is already processing some callback or event, so that a callback isn't lost due to its arrival during processing?
同样,它没有丢失,因为它是一个 队列。它是该数据结构的基本部分。该事件将在队列中等待,直到有东西将其从队列中取出。不管当时有没有监听,它都不会消失,必须消耗掉。
- When an async function completes, does the callback interrupt the event loop and take immediate control, or does the return of an async function re-enter the event loop as a new event at the end of the queue and wait its own turn again? In other words, is a callback from an async function treated like any other event, or differently? If it is treated differently, how? Is this a fundamentally stupid question?
来自异步函数的回调将进入队列,没有任何方法可以 "interrupt" 事件循环的当前流程。事件循环 确实 有多个不同的顺序,因此它可能不会像异步 IO 事件一样被处理(我不记得了),但回调仍然需要等待轮到它。
- Can a callback be blocking, the same way as a badly written event handlers (e.g. HTTP request handler) can? In other words, can badly written code contained in a callback block the server? (I assume the answer is yes but want to know if I'm right.)
是的,回调只是一个函数调用,函数调用不一定是异步的。您可以编写这样的代码来阻止:
function add(a, b, cb) { cb(a + b) }
async.whilst(
function() { return true },
function(cb) { add(1 + 1, cb) },
function() { console.log('Done!') }
)
虽然这段代码在技术上使用了回调,但它不会执行任何异步操作,因此 Node 将继续评估函数调用并且从不检查事件循环。也就是说,您很少看到这种情况,因为回调通常涉及异步操作,否则它们不是为使用回调而编写的。
希望对您有所帮助,如果有任何不清楚的地方,请告诉我!
我正在阅读一本 Node.js 书,试图清楚地了解 Node.js 如何处理事件、异步函数及其回调、非阻塞 I/O 等。以下是我如何理解 事件循环 基础知识的简要概要,然后是我无法在书中找到明确答案的几个问题。如果我的基本理解有任何错误,请指正。那么问题就来了。
据我了解,Node.js 在单个线程上运行所有功能。这包括 事件循环 。换句话说,当 事件 发生时,例如HTTP 请求,该请求进入事件队列。事件循环本身一次从队列中拉出一个事件并对其进行整体处理。这可能意味着 return 立即得到一个简单的结果,或者在 I/O 到第三方(如数据库或文件系统)的情况下,进行非阻塞的异步调用,回调到告诉系统在异步功能完成时要做什么。同时,队列中的所有其他事件都在等待。如果开发人员编写的方法不异步卸载工作或向工作人员卸载,则在处理任务时整个服务器将挂起。
如果有任何错误,请澄清,因为这可能会影响我对以下问题答案的理解,我希望这些问题不会太愚蠢.
- 文件系统、数据库和其他此类调用不会阻塞,因为 Node.js 将它们卸载到异步调用,但是如果 Node.js 是单线程的,谁在监听新事件并管理事件循环?当 Node.js 正在处理一些事件时,谁在监听和管理新传入事件的队列,以便在 Node.js 的注意力在别处时它们不会丢失?我是否从根本上误解了它是如何工作的?除了作为 运行 我们的代码的引擎部分之外,是否有守护进程 运行 之类的东西来管理事件队列?
- 关于异步函数的回调的类似问题......谁在监听和管理传入的回调,而 Node.js 已经在处理一些回调或事件,这样回调就不会因为它的到来而丢失处理中?
- 当异步函数完成时,回调会中断事件循环并立即控制,还是异步函数的 return 在结束时作为新事件重新进入事件循环排队等待轮到自己了?换句话说,来自异步函数的回调是像任何其他事件一样对待,还是有所不同?如果区别对待,又如何呢?这是一个根本愚蠢的问题吗?
- 回调是否可以像写得不好的事件处理程序(例如 HTTP 请求处理程序)一样阻塞?换句话说,回调中包含的编写错误的代码会阻塞服务器吗? (我假设答案是肯定的,但想知道我是否正确。)
这是一个类似的问题,答案很好,但细微差别略有不同。 This linked question解决了用户代码的异步性问题,但其中一个答案似乎包含对我的问题的附带回答。我对用户从不与之交互的 Node 内部工作原理也很感兴趣,例如谁在 Node 阻塞时管理新的客户端请求插入事件队列,对于回调等也是如此。 Is NodeJS really Single-Threaded?
多方搜集,慢慢读。
Node.js 不完全是单线程的。它将磁盘、数据库、HTTP API 调用卸载到其他线程,一旦完成,它们就会在事件循环中排队。
- 还有其他线程参与。
- 事件循环应该是一个类似Queue的数据结构,被很多线程访问
- 大部分时间重新进入事件循环(在队列末尾)。但是有一些方法可以把它放在前面。 (需要检查)
- 是的。例如。如果您使用 fs.readFileSync,它会阻塞服务器一段时间。
事件循环:http://2014.jsconf.eu/speakers/philip-roberts-what-the-heck-is-the-event-loop-anyway.html
凭记忆写的。如果这对你有帮助,我可以尝试查找参考资料。
首先,从这个开始是有帮助的:
短语 "Node.js is single threaded" 有点误导,技术上也不正确。对于代码中的所有意图和目的,您的代码是单线程的,但 Node 本身不是。 Node 中有一些 API 和操作(通常它是异步的 I/O 执行此操作)将在内核或 LibUV 的线程池中使用不同的线程。
现在按每个问题的顺序分解:
- File system, database, and other such calls don't block because Node.js offloads them to asynchronous calls, but if Node.js is single threaded, who is listening for new events and managing the event loop? While Node.js is processing some event, who is listening and managing the queuing of new incoming events so they are not lost while Node.js's attention is elsewhere? Do I fundamentally misunderstand how this works? Is there like a daemon running or something, apart from the part of the engine that is running our code, that manages the event queue?
当 Node 正在处理一些事件时,没有人在监听队列。它们并没有丢失,因为它是一个 queue。它会等到 Node 完成它正在做的事情,这样它就可以 return 到队列中检查它是否有下一步要做的事情。这是 Node "event loop" 的一部分,为什么阻塞代码(永远不允许 Node return 到事件循环顶部的代码,或者需要很长时间才能这样做)是有问题的。
异步 I/O 操作在单独的线程中,可以在 Node 执行其他操作时将内容放入队列。当 Node 完成那件事后,它可以去处理队列上的事情。
- Similar question for asynchronous functions' callbacks ... who is listening for and managing incoming callbacks while Node.js is already processing some callback or event, so that a callback isn't lost due to its arrival during processing?
同样,它没有丢失,因为它是一个 队列。它是该数据结构的基本部分。该事件将在队列中等待,直到有东西将其从队列中取出。不管当时有没有监听,它都不会消失,必须消耗掉。
- When an async function completes, does the callback interrupt the event loop and take immediate control, or does the return of an async function re-enter the event loop as a new event at the end of the queue and wait its own turn again? In other words, is a callback from an async function treated like any other event, or differently? If it is treated differently, how? Is this a fundamentally stupid question?
来自异步函数的回调将进入队列,没有任何方法可以 "interrupt" 事件循环的当前流程。事件循环 确实 有多个不同的顺序,因此它可能不会像异步 IO 事件一样被处理(我不记得了),但回调仍然需要等待轮到它。
- Can a callback be blocking, the same way as a badly written event handlers (e.g. HTTP request handler) can? In other words, can badly written code contained in a callback block the server? (I assume the answer is yes but want to know if I'm right.)
是的,回调只是一个函数调用,函数调用不一定是异步的。您可以编写这样的代码来阻止:
function add(a, b, cb) { cb(a + b) }
async.whilst(
function() { return true },
function(cb) { add(1 + 1, cb) },
function() { console.log('Done!') }
)
虽然这段代码在技术上使用了回调,但它不会执行任何异步操作,因此 Node 将继续评估函数调用并且从不检查事件循环。也就是说,您很少看到这种情况,因为回调通常涉及异步操作,否则它们不是为使用回调而编写的。
希望对您有所帮助,如果有任何不清楚的地方,请告诉我!