Батьківський і дочірній процес
1. Загальний принцип
Коли ти створюєш дочірній процес, Node.js надає канали зв'язку між ним і батьком. Ці канали можна використовувати для:
- передачі текстових даних (stdin/stdout/stderr),
- або двостороннього обміну повідомленнями через IPC (Inter-Process Communication).
2. Варіант 1 - Через стандартні потоки (stdin / stdout / stderr)
Це класичний спосіб спілкування між програмами в UNIX.
Батько надсилає дані в child.stdin,
а дочірній процес читає їх із process.stdin.
Приклад:
main.js
const { spawn } = require('child_process');
// Запускаємо дочірній процес (Node.js-скрипт)
const child = spawn('node', ['child.js']);
// Надсилаємо дані в stdin дочірнього процесу
child.stdin.write('42\n');
child.stdin.end();
// Отримуємо відповідь із stdout
child.stdout.on('data', (data) => {
console.log('Відповідь від дочірнього процесу:', data.toString());
});child.js
process.stdin.on('data', (data) => {
const num = parseInt(data.toString(), 10);
const result = num * 2;
process.stdout.write(`Результат: ${result}\n`);
});Як це працює:
- Батько пише дані в
stdinдочірнього процесу. - Дочірній читає їх через
process.stdin. - Результат повертається через
stdout.
Підходить для:
- запуску CLI-команд, утиліт, зовнішніх програм;
- взаємодії через стандартні потоки (як у shell).
3. Варіант 2 - Через IPC (Inter-Process Communication)
Це вбудований канал зв'язку між процесами Node.js,
який працює лише за створення дочірнього процесу за допомогою fork().
Дозволяє надсилати об'єкти JavaScript, а не лише текст!
Приклад:
main.js
const { fork } = require('child_process');
// Запускаємо дочірній процес Node.js
const child = fork('child.js');
// Надсилаємо об'єкт
child.send({ task: 'calculate', number: 10 });
// Отримуємо відповідь
child.on('message', (msg) => {
console.log('Відповідь від дочірнього процесу:', msg);
});child.js
process.on('message', (msg) => {
if (msg.task === 'calculate') {
const result = msg.number * 2;
process.send({ result });
}
});Що відбувається:
fork()автоматично створює IPC-канал.child.send()надсилає повідомлення дочірньому процесу.process.on('message')у дочірньому процесі отримує його.- Відповідь повертається через
process.send().
Підходить для:
- обміну JSON-даними;
- систем розподілених задач (task workers);
- написання власних "воркерів" на Node.js.
4. Варіант 3 - Через аргументи при запуску
Іноді простіше передати дані один раз під час запуску процесу, наприклад, через аргументи командного рядка.
Приклад:
main.js
const { spawn } = require('child_process');
// Передаємо аргументи в процес
const child = spawn('node', ['child.js', '15']);
child.stdout.on('data', (data) => {
console.log('Відповідь:', data.toString());
});child.js
const num = parseInt(process.argv[2], 10);
console.log('Подвоєне значення:', num * 2);Тут process.argv[2] містить аргумент, переданий від батька.
Підходить для:
- одноразової передачі параметрів;
- скриптів і CLI-команд.
5. Варіант 4 - Через оточення (env)
Ти можеш передати дані дочірньому процесу через змінні середовища.
Приклад:
main.js
const { spawn } = require('child_process');
const child = spawn('node', ['child.js'], {
env: { VALUE: 100 }
});child.js
console.log('VALUE із середовища:', process.env.VALUE);Підходить для:
- конфігурації, ключів, секретів;
- сценаріїв розгортання й DevOps-задач.
6. Порівняння способів передачі даних
| Спосіб | Передача | Тип даних | Підходить для |
|---|---|---|---|
stdin / stdout | Потоки | Текст / бінарні дані | CLI-програми, пайплайни |
child.send() / process.on('message') | IPC | Об'єкти JS | Node.js ↔ Node.js |
| Аргументи командного рядка | Одноразово | Рядки | Прості параметри |
Змінні середовища (env) | Одноразово | Рядки | Конфігурація, секрети |
7. Приклад комбінованої взаємодії
main.js
const { fork } = require('child_process');
const child = fork('child.js');
// Надсилаємо дані
child.send({ action: 'start', payload: [1, 2, 3] });
// Отримуємо відповіді в процесі роботи
child.on('message', (msg) => {
console.log('Повідомлення від дочірнього процесу:', msg);
});
// Завершуємо процес
setTimeout(() => child.kill(), 2000);child.js
process.on('message', (msg) => {
if (msg.action === 'start') {
const result = msg.payload.map(n => n * 2);
process.send({ result });
}
});Це двостороння й повністю асинхронна комунікація
- батько й дитина можуть передавати дані одне одному, не блокуючи потік.
Підсумок
| Підхід | Інструмент | Дані | Двосторонній зв'язок | Особливості |
|---|---|---|---|---|
| Потоки stdin/stdout | spawn, exec | Текст / бінарні | Так | Універсальний, але вимагає серіалізації |
| IPC-канал | fork | Об'єкти JS | Так | Найзручніший між Node.js-процесами |
| Аргументи | spawn, execFile | Рядки | Ні | Одноразова передача |
| Оточення (env) | spawn, exec | Рядки | Ні | Передача конфігурації |
Висновок:
Батьківський процес може надсилати дані дочірньому різними способами:
- через stdin (для зовнішніх програм),
- через IPC (
send()/on('message')) для Node.js-процесів,- через аргументи чи змінні середовища для одноразових параметрів.
Найгнучкіший і найбільш "нативний" для Node.js спосіб - це IPC через
fork(), тому що він дозволяє передавати об'єкти й події, а не лише текст.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.