NodeJS流和过早结束



假设NodeJS中的可读流和与之相关的数据(on('data', ...))事件处理程序相对较慢,是否有可能在最后一个数据处理程序完成之前触发结束事件,如果是这样,它会过早终止该处理程序吗?或者,是否会分派并运行所有数据事件?

在我的情况下,我正在处理大文件,并希望将每个数据块提交到DB。我担心如果End在处理程序中的最后一个DB调用实际完成之前被触发,我可能会丢失最后一个或两个(或更多)记录。

事件'end'触发最后一个'data'事件。但它可能在最后一个Data处理程序完成之前发生。有可能在一个"数据"处理程序完成之前,就启动了下一个处理程序。这取决于你的代码中有什么,但是事件'data'的调用可能在之前完成。它可能会在你的代码中导致错误和问题。

如何引起问题的示例(对您自己的测试):

  var fs = require('fs');
  var rr = fs.createReadStream('somebigfile.jpg');
  var i=0;
  rr.on('data', function(chunk) {
    i++;
    var s = i;
    console.log('readable:' + s);
    setTimeout(function(){
      console.log('timeout:'+s);
    }, 50-i*10);
  });
  rr.on('end', function() {
    console.log('end');
  });

当启动每个'data'事件处理程序时,它将在控制台中打印。几毫秒后,它结束了。完成的顺序可能不同。

<标题>解决方案:

可读流有两个模式'流动模式'和'暂停模式'。当你添加'data'事件处理程序时,你可以自动将可读流设置为流动模式。

来自文档:

当处于流模式时,从底层系统读取数据尽快提供给您的程序

在此模式下,事件将不会等待您的缓慢动作完成。您需要的是'暂停模式'。

从文档:

在暂停模式下,你必须显式调用stream.read()来获取数据块数据输出。流以暂停模式启动。

换句话说:你需要数据块,你得到它,你处理它,当你准备好了,你要求新的数据块。在此模式下,您可以控制何时获取数据。

如何切换到'暂停模式':

是该流的默认模式。但是当你注册'data'事件处理程序时,它切换到'流动模式'。因此不要使用readstream.on('data',...)相反,使用readstream.on('readable', function(){...})时,它的火,那么它意味着流准备给数据块。使用var chunk = readstream.read();

获取数据块

示例来自docs:

var fs = require('fs');
var rr = fs.createReadStream('foo.txt');
rr.on('readable', function() {
  console.log('readable:', rr.read());
});
rr.on('end', function() {
  console.log('end');
});

请阅读文档了解更多细节,因为当流被自动切换到'流动模式'时,有更多的可能性。

使用慢处理程序和流动模式:

如果你想要/需要在"流动模式"下工作,也有解决方案。您可以暂停和恢复流。当你从readstream('data')中得到chunk时,暂停流,当你完成工作后再恢复它。

文档中的例子:

var readable = getReadableStreamSomehow();
readable.on('data', function(chunk) {
  console.log('got %d bytes of data', chunk.length);
  readable.pause();
  console.log('there will be no more data for 1 second');
  setTimeout(function() {
    console.log('now data will start flowing again');
    readable.resume();
  }, 1000);
});

相关内容

  • 没有找到相关文章

最新更新