Що таке дочірні процеси в Node.js?
Дитячі процеси в Node.js
Модуль child_process дозволяє Node.js створювати нові процеси ОС, що дає змогу виконувати командний рядок, запускати інші програми або розподіляти навантаження між кількома процесами.
Чотири основні методи
| Метод | Опис | Сценарій використання |
|---|---|---|
exec() | Виконує команду оболонки, буферизує вивід | Простi команди з невеликим виводом |
execFile() | Виконує файл безпосередньо (без оболонки) | Безпечніше, трохи швидше, ніж exec |
spawn() | Створює процес з потоками | Великий вивід, дані в реальному часі |
fork() | Створює дочірній процес Node.js з каналом IPC | Спілкування між Node.js |
exec() — Команди оболонки
const { exec } = require('child_process');
exec('ls -la', (error, stdout, stderr) => {
if (error) {
console.error('Помилка:', error.message);
return;
}
if (stderr) console.warn('Stderr:', stderr);
console.log('Вивід:', stdout);
});exec() використовує оболонку (обережно з ін'єкцією оболонки!) і буферизує весь вивід в пам'яті.
execFile() — Пряме виконання файлу
const { execFile } = require('child_process');
// Безпечніше — без оболонки, без ризику ін'єкції
execFile('node', ['--version'], (error, stdout) => {
console.log('Версія Node:', stdout.trim()); // v20.0.0
});spawn() — Потоковий вивід
const { spawn } = require('child_process');
const child = spawn('ffmpeg', ['-i', 'input.mp4', 'output.gif']);
// Вивід в реальному часі
child.stdout.on('data', data => {
process.stdout.write(data);
});
child.stderr.on('data', data => {
process.stderr.write(data);
});
child.on('close', code => {
console.log(`Процес завершився з кодом ${code}`);
});Найкраще підходить для великого виводу або тривалих процесів.
fork() — Дочірній процес Node.js з IPC
// child.js
process.on('message', (data) => {
const result = heavyCompute(data.n);
process.send({ result });
});
// parent.js
const { fork } = require('child_process');
const child = fork('./child.js');
child.send({ n: 1000000 });
child.on('message', ({ result }) => {
console.log('Результат:', result);
child.kill();
});fork() подібний до spawn(), але спеціалізований для файлів Node.js і додає вбудований канал IPC (process.send() / process.on('message')).
execSync / spawnSync (Блокування)
const { execSync } = require('child_process');
// Блокує цикл подій — використовуйте лише в скриптах, не на серверах!
const output = execSync('git status').toString();
console.log(output);Обіцянковий варіант
const { exec } = require('child_process');
const { promisify } = require('util');
const execAsync = promisify(exec);
async function getGitLog() {
const { stdout } = await execAsync('git log --oneline -5');
return stdout;
}Або використовуйте child_process/promises (Node.js 15+):
const { exec } = require('child_process/promises');
const { stdout } = await exec('ls -la');Дитячий процес vs Потоки робіт
| Дитячий процес | Потоки робіт | |
|---|---|---|
| Пам'ять | Окрема | Спільна (опціонально) |
| Мова | Будь-яка (оболонка, Python тощо) | Тільки JavaScript |
| Спілкування | Повільний IPC / stdin/stdout | Швидкий MessagePort |
| Ізоляція від аварій | Висока | Нижча |
| Найкраще для | Команд оболонки, програми не на Node | CPU задачі в JS |
Резюме
Дитячі процеси дозволяють Node.js вийти за межі обмеження одного потоку і взаємодіяти з ОС. Використовуйте exec для простих команд, spawn для потокового великого виводу та fork для спілкування між Node.js з IPC.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.