`stream.read()` 或 `stream.once(‘readable’)` 为什么会导致进程终止而没有错误?

huangapple go评论78阅读模式
英文:

Why does `stream.read()` or `stream.once('readable')` kill the process without an error?

问题

当我尝试使用 readable.read()readable.once('redable') 时,我偶然发现一个奇怪的问题。似乎其中一个会在没有任何错误的情况下终止我的Node.js进程。

我本来希望以下代码会抛出一个错误或者无限期挂起:

const { createReadStream } = require('fs');

process.on('unhandledRejection', error => {
  console.log(error)
});

process.on('error', e => {
  console.log('error', e)
});

process.on('exit', e => {
  console.log('exit', e)
});

(async () => {
  // test.txt 是一个空文件
  const stream = createReadStream('test.txt', { encoding: 'utf-8' })
  const waitForReadable = () => new Promise(r => stream.once('readable', r))
  for (let i = 0; i < 1000; i += 1) {
    console.log(i)
    stream.read()
    await waitForReadable()
  }
})()

但实际上,它的输出是:

0
1
exit 0
英文:

While experimenting with readable.read() and readable.once(&#39;redable&#39;) I stumbled upon a peculiar problem. Seems like one of the abote kills my node.js process without any error.

I would expect that the following code will throw an error or will hang indefinitely

const { createReadStream } = require(&#39;fs&#39;);

process.on(&#39;unhandledRejection&#39;, error =&gt; {
  console.log(error)
});

process.on(&#39;error&#39;, e =&gt; {
  console.log(&#39;error&#39;, e)
});

process.on(&#39;exit&#39;, e =&gt; {
  console.log(&#39;exit&#39;, e)
});

(async () =&gt; {
  // test.txt is an empty file
  const stream = createReadStream(&#39;test.txt&#39;, { encoding: &#39;utf-8&#39; })
  const waitForReadable = () =&gt; new Promise(r =&gt; stream.once(&#39;readable&#39;, r))
  for (let i = 0; i &lt; 1000; i += 1) {
    console.log(i)
    stream.read()
    await waitForReadable()
  }
})()

But instead, it outputs:

0
1
exit 0

答案1

得分: 1

createReadStream的行为是,在触发end事件后,它会关闭流并且到达文件末尾。据我所知,没有办法覆盖这个行为。

autoClose似乎可以处理这个问题,但实际上不行。这是文档中唯一描述这一行为的部分。

如果autoClose设置为false,那么文件描述符不会关闭,即使出现错误也不会关闭。关闭文件描述符并确保没有文件描述符泄漏是应用程序的责任。如果autoClose设置为true(默认行为),在errorend时文件描述符将自动关闭。

一旦触发end事件并且所有事件订阅者取消订阅,事件循环将被清除,Node.js会自动终止。

如果您想要实现类似"tail"的体验,您需要使用fs.watchFile

英文:

The way createReadStream behaves is that it closes the stream once it reaches the end-of-file after it fires the end event. There is no way to override this behavior as far as I could find.

autoClose seems like it might handle it, but it does not. This is the only part of the documentation that describes this behavior.

> If autoClose is false, then the file descriptor won't be closed, even if there's an error. It is the application's responsibility to close it and make sure there's no file descriptor leak. If autoClose is set to true (default behavior), on 'error' or 'end' the file descriptor will be closed automatically.

Once the end event is fired and all event subscribers unsubscribe, the event-loop is cleared and Node.js terminates itself.

If you're looking to have a tail-like experience, you will need to go through fs.watchFile

huangapple
  • 本文由 发表于 2023年1月4日 05:28:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/74998811.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定