Контракты EventEmitter
и Readable
тесно связаны через механизм событийной модели Node.js. Readable
поток является расширением EventEmitter
, что формирует мощную абстракцию для работы с данными.
const { Readable } = require('stream');
const { EventEmitter } = require('events');
console.log(Readable.prototype instanceof EventEmitter); // true
Это означает, что все Readable
потоки:
EventEmitter
(on
, emit
, once
и др.)EventEmitter
const readable = new Readable({
read() {
this.push('Hello ');
this.push('World');
this.push(null); // EOF
}
});
readable.on('data', (chunk) => {
console.log('Received chunk:', chunk.toString());
});
readable.on('end', () => {
console.log('No more data');
});
readable.on('error', (err) => {
console.error('Stream error:', err);
});
Базовый скелет Readable
класса:
class Readable extends EventEmitter {
constructor(options) {
super(); // Инициализация EventEmitter
// ... инициализация состояния потока
}
_read(size) {
// Абстрактный метод, должен быть реализован
}
pipe(destination) {
// Реализация pipe использует EventEmitter под капотом
this.on('data', (chunk) => {
destination.write(chunk);
});
this.on('end', () => {
destination.end();
});
}
}
Режимы работы: Readable может работать в:
read()
Буферизация: Readable управляет внутренним буфером, но уведомляет о данных через события
Обратный давление: Реализуется через комбинацию событий и методов:
writable.on('drain', () => {
readable.resume();
});
const readable = fs.createReadStream('file.txt');
readable.on('open', (fd) => {
console.log('File descriptor:', fd);
});
readable.on('ready', () => {
console.log('Stream is ready');
});
readable.on('data', (chunk) => {
console.log('Chunk size:', chunk.length);
readable.pause(); // Приостановка потока
setTimeout(() => readable.resume(), 1000);
});
readable.on('end', () => {
console.log('All data consumed');
});
readable.on('close', () => {
console.log('Stream closed');
});
Readable поток в Node.js — это специализированный EventEmitter с жестко определенным контрактом событий и дополнительной логикой управления потоком данных. Эта связь позволяет использовать всю мощь событийной модели для обработки данных, сохраняя при этом контроль над памятью и ресурсами. Понимание этой связи критически важно для эффективной работы с потоками в Node.js.