В Node.js можно переопределить метод write
у экземпляра Writable
stream, используя паттерн "композиция вместо наследования". Вот как это сделать:
const { Writable } = require('stream');
// Создаем базовый Writable
const writable = new Writable({
write(chunk, encoding, callback) {
// Базовая реализация (может быть пустой)
console.log('Default write:', chunk.toString());
callback();
}
});
// Сохраняем оригинальный метод
const originalWrite = writable.write.bind(writable);
// Переопределяем метод write
writable.write = function(chunk, encoding, callback) {
console.log('Overridden write:', chunk.toString());
// Можно модифицировать данные перед записью
const modifiedChunk = Buffer.from(chunk.toString().toUpperCase());
// Вызываем оригинальный метод с модифицированными данными
originalWrite(modifiedChunk, encoding, callback);
};
// Использование
writable.write('hello');
writable.end();
Для более чистого переопределения:
const { Writable } = require('stream');
const writable = new Writable({
write(chunk, encoding, callback) {
console.log('Internal write:', chunk.toString());
callback();
}
});
Object.defineProperty(writable, 'write', {
value: function(chunk, encoding, callback) {
console.log('Overridden write:', chunk.toString());
// Пропускаем через оригинальный _write
if (typeof encoding === 'function') {
callback = encoding;
encoding = null;
}
this._write(chunk, encoding || 'utf8', callback || (() => {}));
},
writable: true,
configurable: true
});
writable.write('test');
Разница между write
и _write
:
write
- публичный API_write
- внутренний метод, который реализуется в опцияхОбработка callback:
Совместимость с pipe():
const { Writable } = require('stream');
const writable = new Writable({
write(chunk, encoding, callback) {
console.log('Writing:', chunk.toString());
callback();
}
});
const originalWrite = writable.write.bind(writable);
writable.write = function(chunk, encoding, callback) {
// Добавляем префикс ко всем данным
const modified = Buffer.concat([
Buffer.from('PREFIX: '),
Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk, encoding)
]);
originalWrite(modified, 'utf8', callback);
};
process.stdin.pipe(writable);
Основные способы:
Object.defineProperty
Обязательные действия:
Применение:
Ограничения:
Такой подход дает гибкость модификации поведения без создания подклассов, что особенно полезно для быстрого прототипирования и декорации существующих потоков.