我需要两个不同的监听器来读取来自可读流的输入.他们似乎有竞争条件,我想确保我做对了......
当我使用.on('data')时 - 每个侦听器都返回相同的块并可以读取它.
当我使用.on('可读')时 - 第一个捕获事件的侦听器将从缓冲区读取,第二个侦听器将获得一个空缓冲区?
意思是当我有两个听众时,我不能使用.on('可读')事件?
Mic*_*cki 10
TL;DR:数据事件会将数据发送到任意数量的侦听器,但前提是侦听器将在读取数据之前附加,因此使用pipe方法将数据复制到两个PassThrough流并分别从每个流中读取.
详细介绍如下:
首先我们需要了解的是:单个流data每块数据只能产生一次事件。这是因为流对象不“知道”谁在阅读——响应被读取,仅此而已。
现在,只要阅读你的问题,我就会回答——怎么会?该事件将运行两次,因为每个数据事件侦听器都会被调用...除非您实际在readable事件中设置了该侦听器...
假设您进行了如下设置:
response.on("data", function A(chunk) {...});
response.on("readable", function B() {
response.on("data", function C(chunk) {...});
});
Run Code Online (Sandbox Code Playgroud)
现在当一个块1到来时A()将收到块:1。如果流drains 之后(意味着响应太慢以至于无法提供任何新数据),它将暂停。只有在该流可能会readable再次然后B()函数将设置一个监听器C()......但......功能A()已经在读的chunk,因为我们做的是这样C()将仅在下次流工作。
现在正如 Swati Anand 所提到的,您可以使用相同的事件侦听器 - 但在我看来,这将扼杀流的整体美感。使用 apipe会更优雅,像这样:
const PassThrough = require('stream').PassThrough;
const data1 = new PassThrough();
const data2 = new PassThrough();
response.pipe(data1).on("data", function A(){...});
response.pipe(data2);
// when you're ready
data2.on("data", function C(){...});
Run Code Online (Sandbox Code Playgroud)
这背后的想法是 - 我们不监听原始流上的任何事件,而是创建两个类似于“克隆”的传递事件并在data那里读取。这样,程序的每个部分都不会丢失数据。
在Node.js的流文件实际上是对数据流的最佳读取。试着把它读成一个管道故事 - 连接管道等。
当发出可读事件时,两个侦听器都会侦听.但是,第一个调用read()函数将获取数据,第二个将获得一个空缓冲区,因为它是相同的输入流被读取两次并且只有一个块存在.
当数据被发射事件侦听器能够接收从所述流正被读取的数据块.所以所有听众都收到相同的数据.
[编辑]详细说明它的工作原理:
所有可读流以2种模式开始:流动和暂停.默认情况下,所有可读流都以暂停模式开始,但可以使用以下三种方法之一切换到流动模式:
1.将"数据"事件处理程序附加到流中
2.调用stream.resume()方法
3.调用stream.pipe()方法将数据发送到Writable.
当您使用上述任何方法时,流开始流动.它不关心数据侦听器是否附加到流并且可能丢失数据.在内部,在流上调用read()方法,并且读取内部缓冲区中正在累积的任何数据并将其发送给侦听器.内存使用率非常低.
在流上附加可读侦听器时,它优先于数据侦听器,因此您的流仍处于暂停模式.在暂停模式下,您必须通过调用read()方法显式读取内部缓冲区中的数据.当可读数据可用时,它将继续累积在内部缓冲区中,直到显式调用read()方法或恢复流.您可以指定要从内部缓冲区读取的块的大小(以字节为单位),或者返回所有可用数据.当调用read()时,数据事件也会随着读取的数据块一起发出.使用此数据后,内部缓冲区将被清空.因此,如果附加了多个可读事件并尝试使用相同的内部缓冲区,则无法多次获取相同的数据.
我给你的建议是只有一个可读的监听器和多个数据监听器.具有可读性将使您可以灵活地在需要时阅读而不会遗漏任何数据.使用数据事件处理程序,您将能够在所有处理程序中获取该数据.
| 归档时间: |
|
| 查看次数: |
1980 次 |
| 最近记录: |