返回

读写流事件Stream基础之readStream的流动模式和文章搜索

前端

简介

在前面的文章中,我们介绍了Node.js中的流的概念以及如何使用管道(pipe)将数据从一个流传递到另一个流。在本文中,我们将深入探讨可读流(Readable Stream)的流动模式(Flowing Mode),并演示如何使用它来实现文章搜索功能。

readStream的流动模式

在flowing模式下,可读流自动从系统底层读取数据,并通过EventEmitter接口的事件尽快将数据提供给应用。这与默认的暂停模式(Paused Mode)形成对比,在暂停模式下,可读流需要显式地调用read()方法来读取数据。

flowing模式对于处理大量数据非常有用,因为它可以避免显式地调用read()方法来读取数据,从而提高了性能。然而,flowing模式也可能会导致内存问题,因为可读流会将所有读取到的数据都存储在内存中。

为了避免内存问题,可以在可读流上设置一个高水位标记(highWaterMark)。当可读流读取到的数据量达到高水位标记时,可读流会停止读取数据,并触发“drain”事件。应用可以监听“drain”事件,并在该事件被触发时调用read()方法来读取数据。

使用flowing模式实现文章搜索

下面我们演示如何使用flowing模式来实现文章搜索功能。首先,我们需要定义一个SearchTimes类,并继承events模块以便之后使用事件订阅和发布。

const events = require('events');

class SearchTimes extends events.EventEmitter {
  constructor(path) {
    super();
    this.path = path;
  }

  search(query) {
    const readStream = fs.createReadStream(this.path);
    readStream.on('data', (chunk) => {
      const lines = chunk.toString().split('\n');
      lines.forEach((line) => {
        if (line.includes(query)) {
          this.emit('found', line);
        }
      });
    });

    readStream.on('end', () => {
      this.emit('done');
    });
  }
}

接下来,我们需要创建一个SearchTimes实例,并调用search()方法来搜索文章。

const searchTimes = new SearchTimes('./articles.txt');

searchTimes.on('found', (line) => {
  console.log(`Found: ${line}`);
});

searchTimes.on('done', () => {
  console.log('Done searching');
});

searchTimes.search('JavaScript');

性能优化

flowing模式可以显著提高读写操作的性能。然而,如果可读流读取到的数据量过大,可能会导致内存问题。为了避免内存问题,可以在可读流上设置一个高水位标记(highWaterMark)。当可读流读取到的数据量达到高水位标记时,可读流会停止读取数据,并触发“drain”事件。应用可以监听“drain”事件,并在该事件被触发时调用read()方法来读取数据。

以下是如何在可读流上设置高水位标记:

const readStream = fs.createReadStream('./articles.txt', { highWaterMark: 1024 });

总结

本文介绍了如何在flowing模式下使用可读流读取数据,并通过事件订阅和发布来实现文章搜索功能。此外,还讨论了readStream的流动模式对性能的影响以及如何优化读写操作。