【问题标题】:What's better readSync or createReadStream (with Symbol.asyncIterator)?什么是更好的 readSync 或 createReadStream(使用 Symbol.asyncIterator)?
【发布时间】:2020-04-07 08:30:54
【问题描述】:
  1. createReadStream(使用 Symbol.asyncIterator)
async function* readChunkIter(chunksAsync) {
  for await (const chunk of chunksAsync) {
    // magic
    yield chunk;
  }
}

const fileStream = fs.createReadStream(filePath, { highWaterMark: 1024 * 64 });
const readChunk = readChunkIter(fileStream);
  1. 读取同步
function* readChunkIter(fd) {
  // loop
    // magic
    fs.readSync(fd, buffer, 0, chunkSize, bytesRead);
    yield buffer;
}

const fd = fs.openSync(filePath, 'r');
const readChunk = readChunkIter(fd);

生成器函数有什么更好的用途,为什么?

upd:我不是在寻找更好的方法,我想知道使用这些功能的区别

【问题讨论】:

  • 完全取决于用例。有人会说最好始终保持异步,但是如果您的程序在加载关键文件之前无法继续运行,为什么还要为开销而烦恼呢?在您的示例中,它们都以同步方式有效运行。
  • 正如您将在 stackoverflow 上学到的那样,哪个更好完全是意见,直到您提供一些客观标准来判断如何更好并提出问题主要是因为意见不鼓励在这里(并且经常被否决,尽管我没有对你投反对票,因为你是新来的)。我在下面的回答中就您的一般两种方法提供了 cmets(尽量避免对事物的意见方面)。
  • @jfriend00,谢谢你的回答。我真的没有问正确的问题。我不是在寻找更好的方法,我想知道使用这些功能之间的区别。
  • 我在下面的答案中添加了一条关于此的注释。在 stackoverflow 上,如果您意识到您没有传达正确的问题,您可以使用问题下方的“编辑”链接来澄清您的问题(在问题中,而不仅仅是在 cmets 中)。这应该是为了澄清你原来的问题,而不是把它变成一个完全不同的问题(因为这对已经回答了你原来的问题的人是不公平的)。

标签: node.js fs


【解决方案1】:

首先,您将同步文件操作fs.readSync() 与流中的异步操作(内部使用fs.read())进行比较。所以,这有点像供服务器使用的苹果和橘子。

如果这是在服务器上,则永远不要使用同步文件 I/O,除非在服务器启动时,因为在处理请求或任何其他服务器事件时,同步文件 I/O 会在文件读取操作期间阻塞整个事件循环,这会极大地降低您的服务器可扩展性。仅使用异步文件 I/O,这两种情况之间将是流。

否则,如果这不在服务器或任何关心在同步文件操作期间阻塞 node.js 事件循环的进程上,那么您更喜欢哪个接口完全取决于您。


其他cmets:

  1. 还不清楚为什么要将 for await() 包装在生成器中。调用者可以自己使用for await(),避免包装在生成器中。

  2. 读取文件的流通常以事件驱动的方式使用,方法是向data 事件添加事件侦听器并在数据到达时对其进行响应。如果您只是要从文件中异步读取数据块,那么流确实没有任何好处。您也可以使用fs.read()fs.promises.read()

  3. 如果没有看到您尝试编写代码的整体问题,我们无法真正评论解决问题的最佳/更好的方法。您刚刚展示了一点点读取数据的 sn-p。结构的最佳方式取决于更高级别的代码如何最方便地使用/使用数据(您没有显示)。

我真的没有问对问题。我不是在寻找更好的方法,我想知道使用这些功能之间的区别。

嗯,主要区别在于fs.readSync() 是阻塞和同步的,因此阻塞了事件循环,破坏了服务器的可伸缩性,并且永远不应该在服务器环境中使用(启动代码期间除外)。 node.js 中的流是异步的,不会阻塞事件循环。

除此之外,流是比直接读取文件更高级别的结构,应该在您实际使用流的功能时使用,而在您只是从文件中读取块时可能不应该使用直接并且不使用流的任何功能。

尤其是,流的错误处理并不总是那么清晰,尤其是在尝试使用 await 和对流进行承诺时。这可能是因为 readstreams 最初被设计为事件驱动的对象,这意味着在 error 事件上间接传达错误,这使直接读取操作的错误处理变得复杂。如果您不使用读取流的事件驱动性质或某些转换功能或流的其他主要功能,我不会使用它们 - 我会使用更传统的 fs.promises.readFile() 来读取数据。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-02-26
    • 2023-03-17
    • 2020-06-24
    • 2021-03-06
    • 2014-04-28
    • 1970-01-01
    • 2011-10-30
    • 2010-10-08
    相关资源
    最近更新 更多