Skip to main content

Що таке backpressure?

Термін Backpressure - один із ключових принципів потоків (streams) у Node.js. Він пояснює, як система запобігає перевантаженню, коли один потік виробляє дані швидше, ніж інший встигає їх обробляти.

Простими словами

Backpressure (зворотний тиск) - це механізм уповільнення передачі даних у ланцюжку потоків, щоб Writable Stream не "потонув" у даних, якщо Readable Stream надто швидкий.

Уяви шланг із водою: якщо вихід засмічений, тиск зростає - вода тече повільніше. У потоках Node.js усе аналогічно.

Чому це важливо

Без механізму backpressure:

  • Writable Stream переповнив би свій внутрішній буфер,
  • пам'ять процесу (RAM) почала б зростати неконтрольовано,
  • Event Loop завис би від навантаження.

Node.js вирішує це автоматично, якщо ти використовуєш .pipe() чи pipeline().

Як це працює

Кожен потік має внутрішній буфер - область пам'яті, куди тимчасово складаються chunk-и.

  • Writable.write(chunk) повертає true, якщо буфер ще не переповнений.
  • Повертає false, якщо потрібно призупинити читання, поки буфер не звільниться.

Коли буфер знову готовий - потік викидає подію drain, сигналізуючи, що можна продовжувати писати.

Приклад (без pipe)

javascript
const fs = require('fs'); const readable = fs.createReadStream('bigfile.txt'); const writable = fs.createWriteStream('copy.txt'); readable.on('data', (chunk) => { const canContinue = writable.write(chunk); if (!canContinue) { // Буфер переповнений - призупиняємо читання readable.pause(); } }); writable.on('drain', () => { // Буфер звільнився - відновлюємо читання readable.resume(); }); readable.on('end', () => writable.end());

Тут:

  • .write() повертає false, коли Writable не встигає;
  • .pause() і .resume() керують швидкістю читання вручну;
  • .drain повідомляє, коли можна продовжити.

Приклад із pipe (автоматично)

Якщо ти використовуєш .pipe(), то backpressure керується автоматично:

javascript
const fs = require('fs'); fs.createReadStream('bigfile.txt') .pipe(fs.createWriteStream('copy.txt'));
  • .pipe() відстежує, коли Writable перевантажений,
  • призупиняє Readable за потреби,
  • відновлює, коли Writable знову готовий писати.

Як це виглядає логічно

javascript
ReadableWritable Якщо Writable.write()false Readable.pause() ← потік зупинено Коли Writable 'drain' Readable.resume() ← читання відновлюється

Приклад через Transform Stream

Механізм працює й у ланцюжку з кількох потоків:

javascript
const { Transform, pipeline } = require('stream'); const fs = require('fs'); const slowTransform = new Transform({ transform(chunk, _, callback) { setTimeout(() => { this.push(chunk); callback(); }, 100); // штучно уповільнюємо обробку }, }); pipeline( fs.createReadStream('input.txt'), slowTransform, fs.createWriteStream('output.txt'), (err) => { if (err) console.error('Помилка:', err); else console.log('Обробку завершено'); } );

Навіть якщо трансформатор обробляє повільно, Node.js автоматично регулює потік - читання не виконуватиметься швидше, ніж запис.

Основна ідея в одній фразі

Backpressure - це "розумне гальмо", яке запобігає переповненню буфера, забезпечуючи баланс між швидкістю читання й запису.

Коротке порівняння

ПоведінкаБез backpressureЗ backpressure
Потоки читають без зупинкитакні
Пам'ять зростає неконтрольованотакні
Дані втрачаються чи обриваютьсяможливоні
Продуктивність стабільнанітак

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.