Типи потоків
1. Загальне визначення
Потік (Stream) - це абстракція, що дозволяє читати чи записувати дані поступово, по шматках (chunks), не завантажуючи все в пам'ять одразу.
Кожен потік - це об'єкт, який реалізує інтерфейс EventEmitter
(він генерує події на кшталт 'data', 'end', 'error', 'finish').
2. Основні типи потоків у Node.js
| Тип | Призначення | Приклад використання | Основні методи/події |
|---|---|---|---|
| Readable | Читання даних | Читання файлів, HTTP-запитів, stdin | .on('data'), .pipe(), .read() |
| Writable | Запис даних | Запис у файл, HTTP-відповідь, stdout | .write(), .end(), .on('finish') |
| Duplex | Двосторонній потік (читання + запис) | TCP-сокети, WebSocket | .write(), .read(), .pipe() |
| Transform | Duplex + перетворення даних "на льоту" | Стиснення (zlib), шифрування (crypto) | .pipe(), .transform() |
Readable Stream (потік для читання)
Це джерело даних - потік, з якого читають.
Приклади:
- читання файлу через
fs.createReadStream(), - тіло HTTP-запиту (
reqуhttp.createServer()), - потік введення (
process.stdin).
Приклад:
const fs = require('fs');
const readable = fs.createReadStream('file.txt', 'utf8');
readable.on('data', chunk => {
console.log('Отримано шматок:', chunk.length);
});
readable.on('end', () => {
console.log('Читання завершено');
});Потік читає дані поступово й викликає подію 'data' для кожного чанка.
Writable Stream (потік для запису)
Це приймач даних - потік, у який записують.
Приклади:
- запис у файл через
fs.createWriteStream(), - надсилання відповіді (
res) в HTTP-сервері, - виведення в консоль (
process.stdout).
Приклад:
const fs = require('fs');
const writable = fs.createWriteStream('output.txt');
writable.write('Перший рядок\n');
writable.write('Другий рядок\n');
writable.end('Файл записано');
writable.on('finish', () => {
console.log('Запис завершено');
});Потік приймає дані частинами через .write(),
і повідомляє про завершення через подію 'finish'.
Duplex Stream (двонаправлений потік)
Це потік, який може одночасно читати й записувати дані.
Він поєднує можливості Readable і Writable.
Приклади:
- мережеві з'єднання (
net.Socket), - WebSocket-з'єднання,
- потік TCP (один потік читає й пише).
Приклад:
const { Duplex } = require('stream');
const duplex = new Duplex({
read(size) {
this.push('дані з duplex\n');
this.push(null);
},
write(chunk, encoding, callback) {
console.log('Записано:', chunk.toString());
callback();
}
});
duplex.on('data', chunk => console.log('Читання:', chunk.toString()));
duplex.write('Hello Duplex!');Duplex корисний для двостороннього обміну (наприклад, сокети, тунелі, протоколи).
Transform Stream (трансформаційний потік)
Це особливий вид Duplex-потоку, який перетворює дані "на льоту" під час проходження.
Приклади:
- стиснення (
zlib.createGzip()), - шифрування (
crypto.createCipher()), - перетворення тексту (наприклад, у верхній регістр).
Приклад:
const { Transform } = require('stream');
const upperCase = new Transform({
transform(chunk, encoding, callback) {
this.push(chunk.toString().toUpperCase());
callback();
}
});
process.stdin.pipe(upperCase).pipe(process.stdout);Усе, що ти введеш у консоль, виведеться у верхньому регістрі.
3. Взаємодія потоків
Зазвичай потоки з'єднують за допомогою .pipe():
const fs = require('fs');
const zlib = require('zlib');
fs.createReadStream('file.txt')
.pipe(zlib.createGzip()) // Transform stream (стиснення)
.pipe(fs.createWriteStream('file.txt.gz')); // Writable streamТут:
createReadStream→ джерело даних (Readable)createGzip→ перетворення (Transform)createWriteStream→ приймач (Writable)
Потоки з'єднуються як конвеєр (pipeline), передаючи дані частинами без блокування пам'яті.
4. Події та методи потоків
| Тип потоку | Ключові події | Основні методи |
|---|---|---|
| Readable | 'data', 'end', 'error' | .read(), .pipe(), .pause(), .resume() |
| Writable | 'drain', 'finish', 'error' | .write(), .end() |
| Duplex | поєднує обидва набори | .read(), .write() |
| Transform | 'data', 'finish', 'error' | .pipe(), .transform() |
5. Де використовуються ці типи потоків
| Модуль | Використовує потоки |
|---|---|
fs | читання/запис файлів (createReadStream, createWriteStream) |
http | req і res - потоки (Readable/Writable) |
zlib | стиснення / розпакування (Transform) |
crypto | шифрування / хешування (Transform) |
net | TCP-з'єднання (Duplex) |
process | stdin, stdout, stderr - потоки |
Підсумок
| Тип | Призначення | Приклад |
|---|---|---|
| Readable | Джерело даних (читання) | fs.createReadStream(), req |
| Writable | Приймач даних (запис) | fs.createWriteStream(), res |
| Duplex | Читання + запис одночасно | net.Socket, WebSocket |
| Transform | Читання + запис + перетворення | zlib.createGzip(), crypto.createCipher() |
Висновок:
У Node.js існує чотири типи потоків - Readable, Writable, Duplex і Transform.
Вони дозволяють:
- читати, записувати й перетворювати дані поступово,
- працювати з великими файлами й мережевими потоками ефективно,
- і будувати ланцюжки обробки даних без завантаження всієї інформації в пам'ять.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.