关于nodejs线程的一些困惑

Sun*_*Qee 1 asynchronous node.js

我对nodejs线程有一些疑惑.

据我所知,nodejs是在单个线程中运行.如果调用了异步函数,nodejs则会创建一个新线程来运行这些异步代码.异步代码完成后.event loop将获得异步结果并在另一个新线程中触发回调函数.

为了测试,我进行了以下代码测试:

var fs = require("fs");

fs.readFile('package.json','utf-8', function (err, data) {
    if(err)
        console.log(err)
    else
        console.log(data);
});

console.log("before loop");
while(true);
console.log("after loop");
Run Code Online (Sandbox Code Playgroud)

我的预期结果是:

在循环之前
- - package.json内容 - -

实际得到:

在循环之前

在某些地方我可能错了.

问题:

  1. 为什么while(true)阻止readFile()或阻止它的回调函数?
  2. 这些线程之间的关系是什么?

Tad*_*kas 6

你是正确的,因为nodejs在一个线程中运行.您可以启动单独的进程并在这些进程前放置负载均衡器以使用多核处理器,但这并未在节点本身中实现.

但是,节点不会为它遇到的每个异步函数启动一个线程.它将这些函数调用放入不断运行的事件循环中.这里重要的是事件循环是非阻塞的,这意味着函数调用执行的顺序不能得到保证 - 这就是为什么回调是所有node.js程序的基础的原因.这意味着,例如,当一个函数正在等待在文件系统中找到文件并读取到缓冲区时,事件循环不会停止一切等待它完成并继续下一个调用.但这绝不是多线程行为.事件循环不是并行的任何东西,它只是在任务之间不断切换.这只是多任务处理:)

在您的示例中,while(true)阻止事件循环,因为它不是异步函数调用.不要忘记,javascript中的所有内容都不是异步的 - 只有函数调用可以是异步的,而不是其他语言结构,例如循环或条件.因此,在您的示例中,您运行异步文件读取器,该读取器将添加到事件循环并启动.虽然文件系统正在做这件事,但事件循环无关,而是转到console.log("before loop")消息.之后,使用while(true)循环阻止事件循环.这意味着事件循环不能将其置于保持状态并再次转到文件读取器.

希望这能说明问题.这里的主要内容是,并非javascript中的所有内容都必须是异步的,但是处理不同设备(例如文件系统或网络)的大多数耗时操作都是以非阻塞方式实现的.异步函数仅在使用某些外部组件时才有意义 - 您不会使用异步平方根函数,因为它会阻止事件循环.这就是为什么不建议将node.js用于繁重的计算操作(例如音频/视频编码)的原因 - 异步优势在这里没有意义.