Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «worker_threads у Node.js». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)`worker_threads` - вбудований модуль Node.js, що дозволяє виконувати JS-код в окремих потоках паралельно, не блокуючи основний event loop; потоки обмінюються даними через `postMessage`, а не через спільні змінні. **Ключове:** worker_threads підходить для CPU-інтенсивних задач (шифрування, парсинг, обробка зображень), а не для звичайного I/O.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення## Що таке `worker_threads` `worker_threads` - це вбудований модуль Node.js, який дозволяє запускати **JavaScript-код в окремих потоках** (workers). > Простіше кажучи: > це спосіб виконувати кілька JS-задач **паралельно**, використовуючи різні CPU-ядра, > без блокування основного потоку (event loop). ## Навіщо він потрібен Node.js чудово справляється з асинхронними I/O-операціями (мережевими, файловими, БД). Але якщо код виконує **CPU-інтенсивну задачу** (наприклад, шифрування, парсинг, обробку зображень) - вона **блокує event loop**, і сервер перестає відповідати на інші запити. **Рішення:** виносити важкі обчислення в окремі **потоки** за допомогою `worker_threads`. ## 1. Як підключити Модуль вбудований у Node.js (починаючи з версії 10.5, стабільний із 12): ```javascript const { Worker, isMainThread, parentPort } = require('worker_threads'); ``` ## 2. Найпростіший приклад **main.js** ```javascript const { Worker } = require('worker_threads'); console.log('Головний потік:', process.pid); const worker = new Worker('./worker.js'); worker.on('message', msg => console.log('Результат від воркера:', msg)); worker.on('exit', () => console.log('Воркер завершив роботу')); ``` **worker.js** ```javascript console.log('Воркер запущено:', process.pid); let sum = 0; for (let i = 0; i < 1e9; i++) sum += i; postMessage(sum); // Надсилаємо результат у головний потік ``` Що відбувається: - `main.js` запускає воркер в окремому потоці. - Воркер виконує важку задачу (цикл на мільярд ітерацій). - Основний потік **не блокується**. - Коли задача завершена - результат повертається назад через повідомлення. ## 3. Як працює обмін даними Між потоками немає спільного контексту (як у багатопроцесних мовах). Вони **обмінюються повідомленнями** (message passing). | Механізм | Приклад | |---|---| | `parentPort.postMessage(data)` | Воркер надсилає повідомлення в основний потік | | `worker.on('message', handler)` | Основний потік слухає відповідь | | `workerData` | Можна передати дані під час створення воркера | Приклад передавання аргументів: ```javascript const { Worker } = require('worker_threads'); const worker = new Worker('./worker.js', { workerData: { iterations: 1e7 } }); ``` **worker.js** ```javascript const { workerData, parentPort } = require('worker_threads'); let sum = 0; for (let i = 0; i < workerData.iterations; i++) sum += i; parentPort.postMessage(sum); ``` ## 4. Асинхронна версія (через проміс) Для зручності можна обгорнути `Worker` у проміс: ```javascript const { Worker } = require('worker_threads'); function runWorker(path, data) { return new Promise((resolve, reject) => { const worker = new Worker(path, { workerData: data }); worker.on('message', resolve); worker.on('error', reject); worker.on('exit', code => { if (code !== 0) reject(new Error(`Worker stopped with code ${code}`)); }); }); } (async () => { const result = await runWorker('./task.js', { n: 1e8 }); console.log('Результат:', result); })(); ``` ## 5. Коли використовувати worker_threads | Підходить для | Не підходить для | |---|---| | CPU-інтенсивних задач | Звичайного I/O (HTTP, файли, БД) | | Парсингу й обробки великих даних | Простих API-запитів | | Шифрування, стиснення | Асинхронного введення-виведення | | Рендерингу, генерації PDF/зображень | Простої логіки | ## 6. Відмінність від інших способів | Підхід | Модуль | Процес чи потік | Обмін даними | |---|---|---|---| | **worker_threads** | `worker_threads` | Потік (спільна пам'ять) | Швидкий, через повідомлення | | **cluster** | `cluster` | Окремі процеси Node.js | IPC (повільніше) | | **child_process** | `child_process` | Окремий процес | Через stdout/stdin | `worker_threads` працює **в тому самому процесі**, але з **окремим потоком** JS, тому вони **легші й швидші**, ніж процеси `cluster` чи `child_process`. ## 7. Додаткові можливості - Можна використовувати **SharedArrayBuffer** для спільної пам'яті. - Можна передавати **Transferable об'єкти** (ArrayBuffer, MessagePort). - Підтримуються **Atomics** для синхронізації даних. - Підтримка **TypeScript** і **ES Modules** повністю працює. ## 8. Важливо пам'ятати - Потоки-worker не діляться спільним `global` чи `require` - у кожного свій контекст. - Занадто багато воркерів → великі накладні витрати на пам'ять і комунікацію. - Воркер не робить Node.js «багатопоточним» у звичному сенсі - ти **сам** вирішуєш, коли створювати потоки. ## Підсумок | Критерій | Опис | |---|---| | Призначення | Паралельне виконання JS-коду в окремих потоках | | Модуль | `worker_threads` | | Обмін даними | Через `postMessage` / `parentPort` | | Продуктивність | Легше й швидше, ніж процеси | | Підходить для | CPU-інтенсивних задач (математика, парсинг, шифрування) | | З'явився | У Node.js 10.5 (стабільний із 12+) |Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.