读写流事件Stream基础之readStream的流动模式和文章搜索
2023-09-19 02:09:59
简介
在前面的文章中,我们介绍了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的流动模式对性能的影响以及如何优化读写操作。