- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我刚刚创建了一个简单的可读和可写流对,它可以与 pipe() 连接。我对创建背压和控制 Readable 中发生读取的速率感兴趣。但是我对如何实际实现这个或者是否可以使用 Node.js 流感到有点困惑。例如:
const {Writable, Readable} = require('stream');
function getWritable() {
return new Writable({
write: function (chunk, encoding, cb) {
console.log(' => chunk => ', String(chunk));
setTimeout(cb, 1500);
}
});
}
function getReadable(data) {
return new Readable({
encoding: 'utf8',
objectMode: false,
read: function (n) {
// n => Number(16384)
console.log('read is called');
const d = data.shift();
this.push(d ? String(d) : null);
}
});
}
const readableStrm = getReadable([1, 2, 3, 4, 5]);
const piped = readableStrm.pipe(getWritable());
piped.on('finish', function () {
console.log('finish');
});
如果您运行上面的代码,我们会看到 'read is called' 将被记录 5 次,远早于 Writable 中的 write 方法看到数据。
我想做的是仅在 Writable 中的 write 方法触发其回调时调用 Readable 中的 read()
;当然 read() 方法必须先触发一次,但随后会等待可写准备就绪。
有没有办法控制 read()
方法何时以某种方式在可读文件中触发?
最后,我真的不明白read()
方法的目的是什么。
作为一个简单的例子,无论我从 read() 返回什么,我都无法让它停止阅读。 read 方法有什么意义,为什么我们必须实现它?
const Readable = require('stream').Readable;
const r = new Readable({
objectMode: true,
read: function (n) {
console.log('is read');
return false/null/true; // nothing I return here makes a difference
}
});
r.on('data', function (d) {
console.log(d);
});
setInterval(function(){
r.push('valid');
},1000);
最佳答案
Node.js 流非常强大,可以对缓冲中的缓冲和流经它们的数据流提供大量控制。
现在回答你的问题:
A) 您会看到所有数据都先被读取,然后才触发写入,因为您的数据流非常小。如果您使用千字节数据进行测试,您会看到读取流和写入流依次触发。顺序取决于读取流的缓冲容量和写入流产生的背压。例如,TCP 套接字读取流将比磁盘文件写入流快得多,从而产生背压。
B) highWaterMark
是一个强大的读写流构造函数选项。您可以在 documentation 的 Buffering 部分阅读更多相关信息。 . highWaterMark
具体定义了可读/可写流的缓冲容量。默认值为 16kb。在上面的示例中,您可以将 highWaterMark 设置为 2 个字节的可读流,如下所示,您将看到不同之处(在实际情况中不需要,但可以用于学习)。
function getReadable(data) {
let i = 0;
return new stream.Readable({
highWaterWark: 2, // <--- highWaterMark set to 2 byte. Preferably set it to 10 and increase the length of your input array.
encoding: 'utf8',
objectMode: false,
read: function (n) {
// n => Number(16384)
console.log('read is called');
const d = data[i++];
this.push(d ? String(d) : null);
}
});
}
较小的 highWaterMark
值会很快产生背压,并且可能不利于某些用例,例如读取网络数据。
C) 你也可以控制读流和写流的数据流向。如果您的应用程序需要它,那么您可以从可写流控制可读流。具体方法readable.pause()
, readable.read([size])
, readable.resume()
, readable.push(chunk[, encoding])
和 readable.unpipe([destination])
允许您控制可读流中数据的缓冲和流动(甚至来自您的可写流)。事实上,您甚至可以使用方法 readable.unshift(chunk)
将数据从可写流推回到可读流。 . 在可写流中有类似的数据控制方法。
D) read
和write
方法是流实现的一部分。这些方法用于将流数据发送到底层资源,不应直接从您的应用程序数据中调用。基本上,它定义了流的设置。 (不确定我是否能够解释清楚)。
我强烈建议您阅读 Node.js documentation on streams .它将为您提供大量信息(比您从其他各种站点上的示例代码中获得的信息更多)。
希望以上信息对您有所帮助。
关于javascript - 在 Node.js 流中一路实现背压,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41648504/
我是一名优秀的程序员,十分优秀!