Javascript 合并Node.js流
我有一堆文件,我从相应的多个流中读取、处理和合并某些数据到单个流中 有没有比下面更优雅的解决方案(有一个单独的计数器,在所有源流发出Javascript 合并Node.js流,javascript,node.js,stream,Javascript,Node.js,Stream,我有一堆文件,我从相应的多个流中读取、处理和合并某些数据到单个流中 有没有比下面更优雅的解决方案(有一个单独的计数器,在所有源流发出end后调用combinedStream.end()): 您只需使用转换流处理文件,然后通过管道传输到直通流 既然您使用的是let,我想您可以使用ES2015 "use strict"; let fs=require('fs'); let filePaths=['./tmp/h.txt','./tmp/s.txt']; let Stream = re
end
后调用combinedStream.end()
):
您只需使用转换流处理文件,然后通过管道传输到直通流 既然您使用的是
let
,我想您可以使用ES2015
"use strict";
let fs=require('fs');
let filePaths=['./tmp/h.txt','./tmp/s.txt'];
let Stream = require('stream');
class StreamProcessor {
constructor() {
this.process_streams = [];
}
push (source_stream) {
// Create a new Transform Stream
let transform = new StreamTransformer();
// Register the finish event and pipe
transform.processed = transform.wait.call(transform);
source_stream.pipe(transform);
// push the stream to the internal array
this.process_streams.push(transform);
}
done (callback) {
let streams = this.process_streams;
// Wait for all Transform streams to finish processing
Promise.all(
streams.map(function(s) {return s.processed; })
)
.then ( function() {
let combined_stream=new Stream.PassThrough();
streams.forEach(function (stream) {
stream.pipe(combined_stream);
});
// Call the callback with stream
callback(null,combined_stream);
})
.catch(function (err) {
callback(err);
});
}
}
class StreamTransformer extends Stream.Transform {
constructor () {
// call super
super();
}
_transform(chunk,enc, transformed) {
// process files here
let data=chunk.toString();
data=data.substring(0,data.length-2);
this.push(data);
transformed();
}
_flush(flushed) {
// for additonal at end
this.push('\n');
flushed();
}
wait() {
// returns a promise that resolves, when all the data is processed;
let stream = this;
return new Promise(function(resolve,reject) {
stream.on('finish', function() {
resolve(true); });
stream.on('error', function(err) {
reject(err);
});
});
}
}
/// Now you can do..
let process_stream = new StreamProcessor();
filePaths.forEach(function (fpath) {
let fstream = fs.createReadStream(fpath);
process_stream.push(fstream);
});
process_stream.done( function
(err,combined_stream) {
// Consume the combines stream
combined_stream.pipe(process.stdout);
});
测试文件包含“hello”和“stream”
// Outputs is
// hell
// stream
这可以进一步改进…:/ 一种更干净的方法可以用于此,尽管它只不过是将计数器隐藏在某个地方,让您处理一个更舒适的基于回调的模型 这样,您的代码将如下所示:
let sharedStream = ...
function onEachFilename(filename, callback) {
// here you can read from the stream and push the data on the shared one,
// then invoke the "internal" callback on the end event
}
function onEndAll() {
// here you can finalize and close the shared stream
}
forEach(filenames, onEachFilename, onEndAll);
请记住,在某个地方,仍然有一个函数负责为您计数,并在调用所有的
回调
函数后调用onEnd
函数。当然,通过将所有流输送到组合流,将在后者上多次调用结束事件!!我想对于需要从该流中读取的组件来说,这将是一件棘手的事情…@cswl正如我所说的,我不会将整个文件传输到组合流中。只有文件中的一些数据被写入组合流myStream.on('data',myStream.write)
,因此我需要知道何时关闭组合流。@cswl谢谢,但它看起来更复杂,不是吗simpler@kyrylkov. 您可以将这些类放在一个单独的文件中,并将其作为模块加载。然后你的整个代码在//之后变成了
@cswl谢谢。我把它作为另一种解决方案,但不是答案。谢谢。我把它作为替代方案投了赞成票,但不是答案。
let sharedStream = ...
function onEachFilename(filename, callback) {
// here you can read from the stream and push the data on the shared one,
// then invoke the "internal" callback on the end event
}
function onEndAll() {
// here you can finalize and close the shared stream
}
forEach(filenames, onEachFilename, onEndAll);