【问题标题】:Node.js `Stream` and chunk orderNode.js `Stream` 和块顺序
【发布时间】:2019-04-02 02:54:31
【问题描述】:

Node.js streams 的顺序是否保留到并包括 'data' 事件?我相信它们是,this question 似乎也暗示至少 pipe 方法是连续的。

我希望保留块顺序,以便我可以在流结束之前调用一个对每个块进行操作的函数,即在读取流的一部分时,我希望缓冲的数据块由'data' 事件中的函数。

但是,当我运行以下代码时,我使用 Math.randomsetTimeout 专门测试事件是否按顺序发生:

fs.createReadStream(filePath, { encoding: 'ascii' })
  .pipe(streamToEntry)
  .on('data', (chunk) => {
    setTimeout(() => { 
      console.log(chunk); 
    }, Math.random() * 1000)
  });

数据块可以乱序记录。

这是因为setTimeout() 还是因为'data' 事件不一定按顺序调用?即,应该只在pipe 方法中进行有序处理,还是我可以在最后按顺序处理数据?

【问题讨论】:

  • 不用setTimeout试试看。请记住,setTimeout 不保证回调何时运行。它可能发生在 1000 周期的任一侧。再加上你对每个块使用了随机延迟,它们肯定是乱序的
  • @sofcal Math.random 用于测试它们是否会出现故障 - 这当然不是针对任何特定功能 :) 如果没有 setTimeout,它似乎可以工作。但这可能是因为console.log 并不密集。也许使用密集的方法,它会偶尔出现故障。

标签: node.js stream


【解决方案1】:

您的data 事件保证按顺序发出。请参阅this answer 了解更多详细信息以及来自 node 源代码的一些 sn-ps,这表明您确实会按顺序获得您的 data 事件。

当您在data 回调中添加异步代码时会出现问题(setTimeout 是异步代码的一个示例)。在这种情况下,您的 data 回调不能保证按照它们被调用的顺序完成处理。

您需要做的是确保在您的data 回调返回时,您已经完全处理了您的数据。换句话说,您的回调代码需要是同步代码。

fs.createReadStream(filePath, { encoding: 'ascii' })
  .pipe(streamToEntry)
  .on('data', (chunk) => {
      // only synchronous code here
      console.log(chunk); 
  });

要使问题代码起作用,可以使用async/await

fs.createReadStream(filePath, { encoding: 'ascii' })
  .pipe(streamToEntry)
  .on('data', async (chunk) => {
      // only synchronous code here
      await setTimeout(() => console.log(chunk), Math.random() * 1000); 
  });

【讨论】:

  • 怀疑,谢谢。如果有人真的有遇到此问题的setTimeout 用例,我将在您的答案中添加一些内容以帮助上述代码正常工作
猜你喜欢
  • 2017-07-09
  • 1970-01-01
  • 1970-01-01
  • 2014-04-01
  • 2018-08-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-05
相关资源
最近更新 更多