![](/img/trans.png)
[英]how to pipe readable stream to a child_process.exec command using event-stream in node.js?
[英]How to emit/pipe array values as a readable stream in node.js?
创建从数组和管道值到可写流的可读流的最佳方法是什么? 我已经看到使用 setInterval 的 substack示例,我可以成功地使用 0 作为间隔值来实现它,但是我正在迭代大量数据并且每次触发 gc 都会减慢速度。
// Working with the setInterval wrapper
var arr = [1, 5, 3, 6, 8, 9];
function createStream () {
var t = new stream;
t.readable = true;
var times = 0;
var iv = setInterval(function () {
t.emit('data', arr[times]);
if (++times === arr.length) {
t.emit('end');
clearInterval(iv);
}
}
}, 0);
// Create the writable stream s
// ....
createStream().pipe(s);
我想做的是在没有 setInterval 的情况下发出值。 也许使用这样的异步模块:
async.forEachSeries(arr, function(item, cb) {
t.emit('data', item);
cb();
}, function(err) {
if (err) {
console.log(err);
}
t.emit('end');
});
在这种情况下,我迭代数组并发出数据,但从不通过管道传输任何值。 我已经看过 shinout 的ArrayStream ,但我认为它是在 v0.10 之前创建的,它的开销比我正在寻找的要多一些。
您可以通过创建可读流并将值推入其中来解决此问题。
如果您正在使用字符串或缓冲区数组,这将起作用:
'use strict'
const Stream = require('stream')
const readable = new Stream.Readable()
readable.pipe(process.stdout)
const items = ['a', 'b', 'c']
items.forEach(item => readable.push(item))
// no more data
readable.push(null)
笔记:
readable.pipe(process.stdout)
做两件事:将流置于“流动”模式并设置 process.stdout 可写流以接收来自readable
数据Readable#push
方法适用于可读流的创建者,而不是流使用者。Readable#push(null)
以表示没有更多数据。要从既不是字符串也不是缓冲区的数组创建流,您需要可读流和可写流都处于"Object Mode" 。 在下面的示例中,我进行了以下更改:
{objectMode: true}
初始化可读流不是通过管道传输到process.stdout
,而是通过管道传输到处于对象模式的简单可写流。
'use strict' const Stream = require('stream') const readable = new Stream.Readable({objectMode: true}) const writable = new Stream.Writable({objectMode: true}) writable._write = (object, encoding, done) => { console.log(object) // ready to process the next chunk done() } readable.pipe(writable) const items = [1, 2, 3] items.forEach(item => readable.push(item)) // end the stream readable.push(null)
数据来自哪里? 如果它是流数据源,最好使用转换流来操作流,而不是在数组之间进行转换。
从 Node 12.3 开始,您可以改用stream.Readable.from(iterable, [options])
。
const { Readable } = require('stream');
const readableStream = Readable.from(arr);
tl;博士;
这是一个 LIFO 解决方案。 Array.prototype.pop() 具有与 shift 类似的行为,但应用于数组中的最后一个元素。
const items = [1,2,3]
const stream = new Readable({
objectMode: true,
read() {
const item = items.pop()
if (!item) {
this.push(null);
return;
}
this.push(item)
},
})
为此我最终使用了ArrayStream 。 它确实解决了 GC 触发过于频繁的问题。 我收到来自节点的递归 process.nextTick 警告,因此将 ArrayStream 中的 nextTick 回调修改为 setImmediate 并修复了警告,似乎运行良好。
这是一个老问题,但如果有人偶然发现, node-stream-array是 Node.js >= v0.10 的更简单、更优雅的实现
var streamify = require('stream-array'),
os = require('os');
streamify(['1', '2', '3', os.EOL]).pipe(process.stdout);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.