【问题标题】:async _flush won't fire an end eventasync _flush 不会触发结束事件
【发布时间】:2020-10-23 00:39:20
【问题描述】:

'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.resume(),因为我们正在调用 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

【问题讨论】:

    标签: javascript node.js


    【解决方案1】:

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

    这里是一个工作版本,结束事件只有在调用_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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-05-10
      • 2016-06-18
      • 1970-01-01
      • 1970-01-01
      • 2012-02-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多