Какие типы потоков (streams) существуют в Node.js?

Ответ

В Node.js есть четыре основных типа потоков, реализующих соответствующие абстракции:

  1. Readable — поток для чтения данных (например, из файла, HTTP-запроса).

    const fs = require('fs');
    const readableStream = fs.createReadStream('./input.txt');
  2. Writable — поток для записи данных (например, в файл, HTTP-ответ).

    const writableStream = fs.createWriteStream('./output.txt');
  3. Duplex — поток, который одновременно является и Readable, и Writable (например, TCP-сокет).

    const { Duplex } = require('stream');
    const myDuplex = new Duplex({
      read(size) { /* ... */ },
      write(chunk, encoding, callback) { /* ... */ }
    });
  4. Transform — особый тип Duplex-потока, предназначенный для модификации данных на лету (например, сжатие, шифрование).

    const { Transform } = require('stream');
    const upperCaseTransform = new Transform({
      transform(chunk, encoding, callback) {
        this.push(chunk.toString().toUpperCase());
        callback();
      }
    });

Потоки также могут работать в двух режимах:

  • Paused (остановленный): данные читаются только после вызова .read().
  • Flowing (текущий): данные автоматически передаются в обработчики событий, такие как 'data'.

Использование потоков критически важно для эффективной обработки больших объемов данных без загрузки всего набора в память, что является ключевым преимуществом Node.js.

Ответ 18+ 🔞

А, ну это ж классика, ёпта! Сидишь такой, пишешь на Node.js, думаешь — красота, всё летает. А потом бац — файл на 10 гигов подсовывают, и твоё приложение накрывается медным тазом, потому что всю эту овердохуищу данных в память пытается загнать. Вот тут-то и вспоминаешь про потоки, как про молитву.

Смотри, в Node.js есть четыре главных типа этих самых потоков. Не пугайся, всё логично, как в жизни.

  1. Readable — это такой поток, который только сосёт, прости за выражение. Данные откуда-то тянет. С файла, из интернета, откуда угодно.

    const fs = require('fs');
    const readableStream = fs.createReadStream('./input.txt');

    Вот он создался и молчит, ждёт команды. Как будто водопроводный кран открыли, но вода ещё не побежала.

  2. Writable — полная противоположность. Это поток, который только даёт. В него можно писать, и он это куда-то пристроит — в файл, в ответ сервера.

    const writableStream = fs.createWriteStream('./output.txt');

    Представь дыру в стене, куда всё проваливается. Вот это он и есть, только полезный.

  3. Duplex — а это уже хитрая жопа. Он и сосёт, и даёт одновременно. Классический пример — сетевое соединение, тот же TCP-сокет. Ты ему данные шлёшь, а он тебе в ответ что-то своё присылает.

    const { Duplex } = require('stream');
    const myDuplex = new Duplex({
      read(size) { /* ... */ },
      write(chunk, encoding, callback) { /* ... */ }
    });

    Универсальный солдат, бля. И туда, и обратно.

  4. Transform — это вообще магия, особый подвид Duplex'а. Он берёт данные, как-то их по-своему ебёт на лету, и выдаёт уже изменённые. Сжатие, шифрование — вот это всё его рук дело.

    const { Transform } = require('stream');
    const upperCaseTransform = new Transform({
      transform(chunk, encoding, callback) {
        this.push(chunk.toString().toUpperCase());
        callback();
      }
    });

    Закинул ему "привет", а получил "ПРИВЕТ". Красота!

А ещё у них, у этих потоков, два режима работы есть, смотри не перепутай:

  • Paused (остановленный): Сам ничего не делает, сидит как партизан. Чтобы данные пошли, надо ему явно сказать .read() — ну-ка, падла, выдавай что там у тебя!
  • Flowing (текущий): Включил и поехал. Данные сами начинают литься рекой в обработчик события 'data'. Главное — не утонуть, вовремя этот поток притормозить, а то сожрёт всю память.

Вот вся суть в чём, чувак: если ты не хочешь, чтобы твоё приложение бздело и падало под нагрузкой, ты должен эти потоки использовать. Вместо того чтобы весь огромный файл в оперативку тащить, ты его по кусочкам, через эти шланги, прогоняешь. Обработал кусок — выкинул из памяти, взял следующий. Эффективность — пиздец! Именно за это Node.js и любят. Так что не ленись, разбирайся с этой темой, а то будет тебе хиросима, а не сервис.