0

我最近开始阅读 NodeJS(和 JS),对回调在 NodeJs 中的工作方式有点困惑。假设我们做这样的事情:

setTimeout(function(){
    console.log("World");
},1000);
console.log("Hello");

输出:“你好世界”

到目前为止,我读到的 JS 是单线程的,所以事件循环通过一个大堆栈,并且我还被告知不要在回调函数中放置大调用。

1)

好的,所以我的第一个问题是假设它的一个堆栈回调函数是否由主事件循环线程运行?如果是这样,那么如果我们有一个站点通过回调(从数据库获取并推送请求)提供内容,并且我们有 1000 个并发,那么这 1000 个用户基本上是同步服务的,主线程在每个回调函数中执行计算然后继续主事件循环?如果是这种情况,这究竟是如何并发的?

2)如何将回调函数添加到堆栈中,所以可以说我的代码如下所示:

setTimeout(function(){
    console.log("Hello");
},1000);
setTimeout(function(){
    console.log("World");
},2000);

那么回调函数是否会在超时发生之前添加到堆栈中?如果是这样,是否设置了一个标志来通知主线程回调函数已准备好(或者是否有另一种机制)。如果这确实是正在发生的事情,它不仅会使堆栈膨胀,尤其是对于具有回调函数的大型 Web 应用程序,而且堆栈越大,运行所需的时间就越长,因为线程必须单步执行整个事情。

4

2 回答 2

1

回调函数不会添加到调用者堆栈中。这里没有递归。它们是从事件循环中调用的。尝试console.log在您的示例中替换并观察结果 - 堆栈没有增长。

于 2013-04-11T03:09:31.863 回答
1

事件循环不是堆栈。最好将其视为队列(先进/先出)。最常见的用途是执行 I/O 操作。

假设您想从磁盘读取文件。你先说嘿,我想读这个文件,当你读完之后,调用这个回调。当实际的 I/O 操作在一个单独的进程中执行时,Node 应用程序可以自由地继续做其他事情。当文件完成读取时,它会在事件循环的队列中添加一个项目以指示完成。节点应用程序可能仍在忙于做其他事情,或者可能有其他项目等待首先出列,但最终我们的完成通知将被节点的事件循环出列。它将与我们的回调匹配,然后回调将按预期调用。当回调返回时,事件循环将下一个项目出列并继续。当节点的事件循环中没有任何内容时,应用程序退出。

这是事件循环如何工作的粗略近似,而不是精确的技术描述。

对于特定setTimeout情况,可以将其视为优先级队列。至少在该时间过去之前,节点不会考虑将项目/作业/回调出队。

有很多关于 Node/JavaScript 事件循环的精彩文章,如果您感到困惑,您可能想阅读这些文章。

于 2013-04-11T03:38:12.987 回答