我有一个简单的应用程序运行,通过流管道对象,如下所示:
new ReadStreamThatCreatesData()
.pipe(new TransformerStream())
.pipe(new WriteStreamThatActsOnData()
但我希望WriteStreamThatActsOnData
能够访问ReadStreamThatCreatesData
中的某个媒体资源,而TransformerStream
无需了解该资产或能够访问它。我想要的伪代码基本上是这样的:
new ReadStreamThatCreatesData()
.storeContext((obj) => obj.property)
.pipe(new TransformerStream())
.retieveContext((obj, context) => obj.property = context)
.pipe(new WriteStreamThatActsOnData()
但考虑到溪流的性质,我真的不明白这是怎么回事。有没有人对我如何做这样的事情有任何明智的想法?
答案 0 :(得分:0)
我能想到的一种方法是将ReadStreamThatCreatesData传递给一个函数,该函数将它分成两个不同的流:一个是从项中拉出的上下文属性流,另一个是流与对象的其余部分。您将第二个流传输到TransformerStream中,然后通过将两个流组合成一个的zip运算符将该输出与上下文流一起传输。然后将其发送到WriteStreamThatActsOnData。
我认为没有内置的node.js函数来执行此操作,但您可以使用其他库,例如RxJS或highland。
以下是高地的示例实现:
'use strict';
/*
Put this content into input.txt. Make sure there are no blank lines in the file:
{ "secret": 1, "val": "a" }
{ "secret": 2, "val": "b" }
{ "secret": 3, "val": "c" }
{ "secret": 4, "val": "d" }
{ "secret": 5, "val": "e" }
After running, output.txt should have this content:
{"val":"A","secret":1}
{"val":"B","secret":2}
{"val":"C","secret":3}
{"val":"D","secret":4}
{"val":"E","secret":5}
*/
const fs = require('fs');
const stream = require('stream');
const highland = require('highland');
const input = fs.createReadStream('input.txt');
const output = fs.createWriteStream('output.txt');
function readStreamThatCreatesData() {
return highland(input).split().map(JSON.parse);
}
class TransformerStream extends stream.Transform {
constructor(options) {
if (!options) {
options = {};
}
options.objectMode = true;
super(options);
}
_transform(item, enc, cb) {
if (item.secret) {
item.secret = 'removed';
}
item.val = item.val.toUpperCase();
this.push(item);
cb();
}
};
function removeSecret(item) {
delete item.secret;
return item;
}
function extractSecret(item) {
return item.secret;
}
const inputStream = readStreamThatCreatesData();
const secretStream = inputStream.fork().map(extractSecret);
const mainStream = inputStream.fork().map(removeSecret);
secretStream.zip(highland(mainStream.pipe(new TransformerStream())))
.map((combined) => {
const secret = combined[0];
const item = combined[1];
item.secret = secret;
return JSON.stringify(item) + '\n';
})
.pipe(output);