代码之家  ›  专栏  ›  技术社区  ›  sezanzeb

async_flush不会触发结束事件

  •  0
  • sezanzeb  · 技术社区  · 4 年前

    “end”事件从未触发,除非添加了“data”处理程序或 pipe.resume() 被调用,如下所示: https://nodejs.org/api/stream.html#stream_compatibility_with_older_node_js_versions

    但我们不仅在打电话 pipe.end() 与那里的例子相反,我们也在调用 pipe.read() 重复如下所述: https://nodejs.org/api/stream.html#stream_event_end

    const { Transform } = require('stream')
    
    class Pipe extends Transform {
        _transform(data, encoding, callback) {
            console.log('_transform', data.toString())
            this.push(data)
            callback()
        }
    
        _flush(callback) {
            process.nextTick(callback)
        }
    }
    
    const pipe = new Pipe()
    
    pipe.on('finish', () => {
        console.log('on finish')
    })
    
    pipe.on('end', () => {
        console.log('on end')
    })
    
    pipe.write('foo')
    
    console.log('pipe.end()')
    pipe.end()
    
    console.log('read 1', pipe.read().toString())
    console.log('read 2', pipe.read())
    

    输出:

    _transform foo
    pipe.end()
    read 1 foo
    read 2 null
    on finish
    

    我们希望看到一个“结束”日志,即使没有数据处理程序和 管道恢复() 既然我们在打电话 pipe.read() .

    此外,使用

    _flush(callback) {
        callback()
    }
    

    相反,它工作得很好:

    _transform foo
    pipe.end()
    read 1 foo
    read 2 null
    on finish
    on end
    

    因此,这个问题似乎只存在于异步_flush代码中

    那里发生了什么事?

    节点版本10.19.0~dfsg-3ubuntu1

    0 回复  |  直到 4 年前
        1
  •  0
  •   sezanzeb    4 年前

    我刚刚意识到我忘了更新这个问题。

    这是一个工作版本,只有在调用_flush回调函数后,以及在结束事件被消耗后,才会触发结束事件(请参见 https://github.com/nodejs/node/issues/34520#issuecomment-664646155 )

    const { Transform } = require('stream')
    
    async function main() {
        let resolveFlush
        const flush = new Promise(resolve => {
            resolveFlush = resolve
        })
    
        class Pipe extends Transform {
            _transform(data, encoding, callback) {
                console.log('_transform', data.toString())
                this.push(data)
                callback()
            }
    
            _flush(callback) {
                process.nextTick(() => {
                    console.log('flush callback')
                    callback()
                    resolveFlush()
                })
            }
        }
    
        const pipe = new Pipe()
    
        pipe.on('finish', () => {
            console.log('on finish')
        })
    
        pipe.on('end', () => {
            console.log('on end')
        })
    
        pipe.write('foo')
    
        console.log('pipe.end()')
        pipe.end()
    
        console.log('read 1', pipe.read().toString())
        console.log('read 2', pipe.read())
    
        await flush
        console.log('read 3', pipe.read())
    }
    
    main()
    

    输出

    _transform foo
    pipe.end()
    read 1 foo
    read 2 null
    on finish
    flush callback
    read 3  null
    on end