我遇到了在流中进行异步调用的问题。看起来由于某种原因,如果我有三个流并且中间流进行异步调用,则最终流永远不会收到'结束'事件。我可以使用一些简单的through流和超时来模拟行为。
var options = {}
var streamOne = function(){
return through(function write(row){
this.emit('data', row)
})
}
var streamTwo = function(){
return through(function write(row){
this.pause()
var that = this;
setTimeout(function(){
that.emit('data', row)
that.resume()
}, 1000)
})
}
options.streams = [new streamOne(), new streamTwo()]
然后我将其传递给event-stream。
var streams = []
//Pass stream one and stream two to es.pipe
streams.push(es.pipe.apply(this, options.streams))
//Then add the final stream
var endStream = es.pipe(
new streamThree()
)
streams.push(endStream)
//And send it through the pipeline
es.pipeline.apply(this, streams)
因此,这在当前情况下不起作用。
一些令人困惑的问题:如果我删除streamOne,它会起作用!如果streamTwo没有进行异步调用,则可以正常工作。这让我觉得问题在于两个流交互的方式。但是,如果我在整个代码中console.log
,看起来一切正常,streamThree将编写数据但从不注册'end'事件。 *注意:streamThree不使用through,而是使用本机Streams模块。
关于为什么会这样的想法?
答案 0 :(得分:1)
运行一些测试用例后,看起来管道或通过I / O没有正确处理。我不完全确定为什么会这样,但我认为这是一个竞争条件,暂停和恢复导致问题的流。我做了一些事情来清理代码:
1)简化管道。我没有直接在流水线中嵌套es.pipe
,而是直接放入流。这有助于更好地管理流之间的数据流。
2)我没有从常规直流中发出数据,而是使用this.queue
对数据进行排队,让模块处理潜在的背压。
3)我使用事件流方法es.map来处理异步调用的流程。 我认为这是一个更好的解决方案,因为它更干净地处理流的暂停和恢复,仍然返回直通。