简体   繁体   English

使用node.js在流中进行异步调用的问题

[英]Problems with making async calls in streams using node.js

I am having a problem with making async calls in my streams. 我在流中进行异步调用时遇到问题。 It looks like for some reason if I have three streams and the middle stream makes an async call, the final stream never receives the 'end' event. 由于某些原因,如果我有三个流,并且中间流进行异步调用,则最终流永远不会收到“ end”事件。 I can simulate the behavior with some simple through streams and a timeout. 我可以通过一些简单的流和超时来模拟行为。

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()]

I then pass this through to event-stream . 然后,我将其传递给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)

So, this does not work in the current case. 因此,这在当前情况下不起作用。

A couple of confusing points: if I remove streamOne, it works! 有两点令人困惑:如果删除streamOne,它会起作用! If streamTwo does not make an async call, it works. 如果streamTwo没有进行异步调用,则它可以工作。 This makes me think the problem lies in the way the two streams interact. 这使我认为问题出在两个流交互的方式上。 However, if I console.log throughout the code, it looks like everything works fine, streamThree will write the data but never registers the 'end' event. 但是,如果我在整个代码中使用console.log ,看起来一切正常,streamThree会写入数据,但永远不会注册“ end”事件。 *Note: streamThree is not using through, and is instead using the native Streams module. *注意:streamThree未使用直通,而是使用本机Streams模块。

Thoughts on why this is happening? 关于为什么会这样的想法?

After running some test cases, it looks like the I/O was not being handled properly by the pipeline or by through. 在运行了一些测试用例之后,看起来好像管道或直通没有正确处理I / O。 I'm not entirely sure why this was the case, but I think it was a race condition with the pausing and resuming of the stream that was causing the problem. 我不完全确定为什么会这样,但是我认为是由于争用情况而导致的流暂停和恢复。 I did a few things to clean up the code: 我做了一些事情来清理代码:

1) Simplify the pipeline. 1)简化管道。 Rather than doing nested es.pipe s inside the pipeline, I just put the streams in directly. 我没有直接在管道中嵌套es.pipe ,而是直接将流放入其中。 This helped to better manage the flow of data between the streams. 这有助于更好地管理流之间的数据流。

2) Instead of emitting data from my regular through stream, I queued the data using this.queue , letting the module handle potential backpressure. 2)我没有使用常规流发送数据,而是使用this.queue对数据进行this.queue ,让模块处理潜在的背压。

3) I used the event-stream method es.map to handle the flow of the asynchronous call. 3)我使用事件流方法es.map来处理异步调用的流程。 I think this was a better solution since it more cleanly handles the pausing and resuming of the stream and still returns a through stream. 我认为这是一个更好的解决方案,因为它可以更干净地处理流的暂停和恢复,并且仍然返回直通流。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM