Короткий ответ: поток в Node.js — это способ работать с данными по частям. Обычный подход сначала получает все данные целиком, а stream позволяет читать, передавать или записывать их постепенно: кусок за куском
Запрос про streams обычно возникает, когда человек уже умеет читать файл через fs.readFile, но сталкивается с большими файлами, видео, логами, загрузками или HTTP-ответами. В таких задачах нельзя всегда держать все данные в памяти, и потоки становятся не “сложной теорией”, а практическим способом не уронить приложение
Обычные данные и поток на простом примере
Обычное чтение файла выглядит так
const fs = require("fs");
fs.readFile("big-file.txt", "utf8", (error, data) => {
if (error) {
console.error(error);
return;
}
console.log(data);
});
Здесь Node.js читает файл целиком, кладет его в память и только потом вызывает функцию. Для маленького файла это нормально. Для файла на несколько гигабайт — уже проблема
Потоковый вариант
const fs = require("fs");
const stream = fs.createReadStream("big-file.txt", {
encoding: "utf8"
});
stream.on("data", (chunk) => {
console.log("Получен кусок:", chunk.length);
});
stream.on("end", () => {
console.log("Файл прочитан");
});
stream.on("error", (error) => {
console.error("Ошибка чтения", error);
});
Здесь файл читается частями. Node.js не обязан держать весь файл в памяти сразу
Что такое chunk
chunk — это очередной кусок данных, который пришел из потока. Размер куска зависит от настроек и источника данных. Для новичка важна сама идея: программа получает не весь файл сразу, а серию фрагментов
Если представить файл как ведро воды, обычное чтение пытается поднять все ведро сразу. Stream открывает кран и дает воде течь постепенно
Что делает pipe
pipe соединяет читающий поток с пишущим потоком. Например, можно скопировать файл без ручной обработки каждого куска
const fs = require("fs");
const readStream = fs.createReadStream("input.txt");
const writeStream = fs.createWriteStream("output.txt");
readStream.pipe(writeStream);
Этот код читает input.txt и записывает данные в output.txt. Node.js сам передает куски из одного потока в другой
Где streams встречаются в реальной работе
Потоки встречаются чаще, чем кажется
- чтение больших файлов
- запись логов
- скачивание файлов по HTTP
- отдача файлов пользователю
- обработка CSV
- загрузка изображений
- проксирование данных между сервисами
Если вы отдаете большой файл через сервер, stream позволяет начать отправку раньше, не дожидаясь полной загрузки файла в память
Пример: отдать файл через HTTP-поток
const http = require("http");
const fs = require("fs");
const server = http.createServer((request, response) => {
const stream = fs.createReadStream("video.mp4");
stream.on("error", () => {
response.statusCode = 404;
response.end("Файл не найден");
});
stream.pipe(response);
});
server.listen(3000, () => {
console.log("Сервер запущен: http://localhost:3000");
});
Здесь файл передается в ответ постепенно. Это намного практичнее для крупных файлов, чем сначала читать весь файл через readFile
Чем stream сложнее обычных данных
С потоком нужно думать о событиях: data, end, error. Также важно учитывать backpressure — ситуацию, когда источник данных отдает быстрее, чем получатель успевает обработать. pipe помогает с этим лучше, чем ручная обработка
Для первого знакомства не нужно сразу уходить в низкоуровневую механику. Достаточно понять: stream — это данные во времени, а не готовая переменная со всем содержимым
Мини-практика
Создайте большой текстовый файл или возьмите любой файл больше нескольких мегабайт. Прочитайте его через fs.createReadStream, выведите количество полученных чанков и сравните с обычным fs.readFile
Дополнительное упражнение: скопируйте файл через readStream.pipe(writeStream) и проверьте, что копия появилась
Частые ошибки
Не обработали error Если файл не найден или нет прав доступа, поток выдаст ошибку. Всегда добавляйте обработчик error
Ждут, что stream сразу вернет данные Поток работает через события или через pipe. Он не возвращает весь файл как обычная строка
Используют readFile для больших файлов Для маленьких файлов это нормально. Для больших файлов лучше поток
Слишком рано закрывают response Если вы используете pipe(response), не вызывайте response.end() вручную раньше времени
Что почитать дальше по Node.js
Если нужен общий маршрут по теме, откройте рубрику Node.js. Для соседних задач пригодятся эти разборы:
- Node.js + MySQL: REST API для первых данных
- Как запустить терминал Node.js и чем он отличается от обычной консоли
- Node.js + MongoDB: первая коллекция из приложения
- Node.js LTS: какую версию ставить новичку



