为什么当 stdout 超过缓冲区大小时只发出一个 'data' 事件?

Why is only one 'data' event emitted when stdout exceeds the buffer size?

背景:https://github.com/Almenon/AREPL-vscode/pull/332 (内容很多,建议先往下看)

我假设节点在 highWaterMark is reached. Is this correct? It looks like the answer is yes according to this stackoveflow 时刷新标准输出。假设是这样,如果超过高水位线,额外的字符应该在第二次冲洗中出现,对吗?

无论缓冲区大小如何,节点似乎都忽略了高水位线并且只刷新了一次。

用预期/实际结果重现我的问题的示例代码:

import { spawn } from "child_process"

// 8192*2 (16384 aka 16KB) is the highWaterMark (aka buffer size?)
const node_process = spawn("node", ["-e", "process.stdout.write('a'.repeat(8192*2+1));setTimeout(()=>{console.log('done')},4000)"])

node_process.on('error', err => console.error(err))

let numFlushes = 0
node_process.stdout.on('data', (buffer: Buffer) => {
    numFlushes += 1
    const str = buffer.toString()
    console.log(`flush number: ${numFlushes}\
    Buffer length: ${buffer.length}`)
    if (buffer.length < 20) console.log(str)
})

/*
Expected result: 3 flushes, one when highWaterMark is reached, another with rest of stdout, final with done log
Acutal result: 2 flushes. All of stdout is recieved at once. 4 seconds later comes the done log.
Related docs: https://nodejs.org/docs/latest-v12.x/api/stream.html#stream_buffering
OUTPUT (courtesy of quokka)
flush number: 1    Buffer length: 16385
  at ​​​`flush number: ${ numFlushes }\ Buff...​​​ ​personal/test_node_buffer.ts:11:4
flush number: 2    Buffer length: 11
  at ​​​`flush number: ${ numFlushes }\ Buff...​​​ ​personal/test_node_buffer.ts:11:4
done
  at ​​​str​​​ ​personal/test_node_buffer.ts:13:8
*/

https://gist.github.com/Almenon/6286ca1baf0714b56dc133e03728eb12

我已经在 Windows 10 上对此进行了测试。 在 linux 上,如果您执行 *8+2 它会按预期进行 3 次刷新。奇怪的。 除此之外,两个平台具有相同的行为。

https://repl.it/@almenon/testBufferSize

https://github.com/nodejs/node/issues/33465

节点“在需要时”发出数据事件

是的,这是认真的答案。