当前位置: 首页 > 面试题库 >

Node.js流如何工作?

田瀚
2023-03-14
问题内容

我对Node.js流有疑问-特别是它们在概念上如何工作。

不缺少有关如何使用流的文档。但是我很难找到流在数据级别如何工作。

我对Web通信HTTP的有限理解是,来回发送完整的数据“包”。类似于个人订购公司目录,客户端向服务器发送GET(目录)请求,然后服务器以目录进行响应。浏览器不会收到目录的页面,而是会收到整本书。

节点流可能是多部分消息吗?

我喜欢REST模型-
尤其是它是无状态的。浏览器与服务器之间的每一次交互都是完全自给自足的。因此,节点流不是RESTful的吗?一位开发人员提到与插座管的相似之处,插座使连接保持打开状态。回到我的目录订购示例,这就像是一条信息电视广告,其行为“但是,等等!还有更多!”
而不是完全包含的目录?

流的很大一部分是接收器“下游”向上游发送“暂停”和“继续”之类的消息的能力。这些消息由什么组成?他们是POST吗?

最后,我对Node工作原理的有限视觉理解包括此事件循环。可以将函数与线程池放在不同的线程上,然后事件循环继续进行。但是,在数据流完成之前,是否不应该发送数据流使事件循环占据(即停止)?它还如何监视下游的“暂停”请求?n事件循环是否将流放在池中的另一个线程上,并且当遇到“暂停”请求时,检索相关线程并暂停它?

我已经阅读了node.js文档,完成了nodeschool教程,构建了一个heroku应用,购买了两本书(真实,自含,书籍,有点像之前讲过的目录,可能不喜欢节点流),问了几个“节点”代码训练营的讲师-
所有人都在谈论如何使用流,但没有人谈论下面实际发生的事情。

也许您遇到了很好的资源,解释了它们如何工作?对于非CS头脑来说,也许是一个很好的拟人类比?


问题答案:

首先要注意的是:node.js流不限于HTTP请求。HTTP请求/网络资源只是node.js中流的一个示例。

对于所有可以小块处理的事物,流都是有用的。它们使您能够以较小的块处理潜在的巨大资源,从而更轻松地将其装入RAM。

假设您有一个文件(大小为数GB),并且想要将所有小写字母转换为大写字母并将结果写入另一个文件。天真的方法将使用读取整个文件fs.readFile(为简便起见,省略了错误处理):

fs.readFile('my_huge_file', function (err, data) {
    var convertedData = data.toString().toUpperCase();

    fs.writeFile('my_converted_file', convertedData);
});

不幸的是,此方法很容易使您的RAM不堪重负,因为在处理文件之前必须先存储整个文件。您还将浪费宝贵的时间等待文件被读取。以较小的块处理文件是否有意义?您可以在等待硬盘提供剩余数据的同时获得第一个字节后立即开始处理:

var readStream = fs.createReadStream('my_huge_file');
var writeStream = fs.createWriteStream('my_converted_file');
readStream.on('data', function (chunk) {
    var convertedChunk = chunk.toString().toUpperCase();
    writeStream.write(convertedChunk);
});
readStream.on('end', function () {
    writeStream.end();
});

这种方法更好:

  1. 您将只处理很容易装入RAM的一小部分数据。
  2. 一旦第一个字节到达,您就开始处理,不要浪费时间做任何事情,而要等待。

打开流后,node.js将打开文件并开始从中读取。一旦操作系统将一些字节传递给正在读取文件的线程,它将被传递给您的应用程序。

回到HTTP流:

  1. 第一个问题在这里也是有效的。攻击者可能会向您发送大量数据,以淹没您的RAM并关闭(DoS)服务。
  2. 但是,在这种情况下,第二个问题更为重要:网络可能非常慢(例如智能手机),并且可能需要很长时间才能将所有内容发送给客户端。通过使用流,您可以开始处理请求并缩短响应时间。

暂停HTTP流时:这不是在HTTP级别完成的,但是要低得多。如果您暂停流,node.js将仅停止从底层TCP套接字读取。然后,所发生的事情取决于内核。它仍然可以缓冲传入的数据,因此在您完成当前工作后就可以使用了。它还可以在TCP级别通知发送方它应该暂停发送数据。应用程序不需要处理这些。那不关他们的事。实际上,发件人应用程序甚至可能没有意识到您不再积极阅读!

因此,基本上,这是关于在可用时立即提供数据,但又不会占用您的资源。底层的辛勤工作是由操作系统或者进行(例如netfshttp),或者通过流的作家,你正在使用(例如,zlib它是一个Transform流,并且通常用螺栓固定fsnet)。



 类似资料:
  • 问题内容: 我不了解关于nodejs的几件事。每个信息来源都说,由于缺少线程锁定和上下文切换,node.js比标准线程化Web服务器更具可伸缩性,但是我想知道,如果node.js不使用线程,它将如何并行处理并发请求?事件I / O模型意味着什么? 非常感谢您的帮助。谢谢 问题答案: 节点完全是事件驱动的。基本上,服务器由一个线程处理一个事件接着另一个事件组成。 一个新的请求进入是一种事件。服务器开

  • 问题内容: 根据Node0.4.3的API文档,该函数启动一个例程,该例程将 注意上的更改。每次访问文件时都会调用该侦听器。 它还说 提供的if应该是包含两个成员的对象,boolean 和,以毫秒为单位的轮询值 这表明它将每隔一段时间检查一次。但这也说 默认值为。 那么这是否意味着它将每毫秒检查一次文件时间是否更改?它是否监听操作系统级别的事件?这是如何运作的? 问题答案: 是的,cpedros是

  • 问题内容: 在我提出疑问之前,我至少应该解释一下使用中间件时发生的事情。要使用中间件,要使用的功能是。在执行中间件时,它将使用或使其调用下一个中间件,从而不再调用任何中间件。这意味着我放置中间件调用的顺序很重要,因为某些中间件依赖于其他中间件,而接近末尾的某些中间件甚至可能不会被调用。 今天,我正在开发应用程序,并在后台运行服务器。我想进行一些更改并刷新页面,然后立即查看更改。具体来说,我正在更改

  • 问题内容: 我尝试了这个: 所以我想象require()可能是这样实现的: 那正确吗?请帮助我了解require()或在哪里可以找到源代码。谢谢! 问题答案: 源代码在这里。/ 不是关键字,而是全局变量。你的主要脚本包前开始在其拥有所有喜欢全局的功能,等在其上下文。 请注意,虽然module.js本身正在使用,但这是一个不同的require函数,它是在名为“ node.js”的文件中定义的 上面的

  • 集日程、项目、会议、文档等其他协同办公能力于一体的一站式办公工具平台。

  • 请求接口的代码: