В онлайн-обучающем видео я смотрю, чтобы узнать Node, рассказчик говорит, что "spawn лучше для более длинных процессов, связанных с большими объемами данных, тогда как выполнение лучше для коротких бит данных".
Почему это? В чем разница между функциями child_process spawn и execute в Node.js, и когда я знаю, какой из них использовать?
Основным отличием является то, что spawn
больше подходит для длительных процессов с огромным выходом. ввод/вывод потоков spawn
с дочерним процессом. буферизованный вывод exec
в небольшом (по умолчанию 200K) буфере. Также, как я знаю, exec
сначала вызывает подоболочку, затем попытайтесь выполнить ваш процесс. Если коротко, коротко, используйте spawn
в случае, если вам нужно много данных, передаваемых из дочернего процесса, и exec
если вам нужны такие функции, как конвейеры оболочки, перенаправления или даже если вам нужно выполнить несколько программ за один раз.
Несколько полезных ссылок - DZone Hacksparrow
Хорошее место для начала - документация NodeJS.
Для "порождения" состояние документации:
Метод child_process.spawn() порождает новый процесс, используя данную команду с аргументами командной строки в аргументах. Если опущено, args по умолчанию является пустым массивом.
В то время как для "exec":
Создает оболочку, затем выполняет команду в этой оболочке, буферизируя любой сгенерированный вывод. Командная строка, передаваемая в функцию exec, обрабатывается непосредственно оболочкой, и специальные символы (в зависимости от оболочки) должны обрабатываться соответствующим образом.
Похоже, главное - нужно ли вам обрабатывать вывод команды или нет, что, я думаю, может повлиять на производительность (я не сравнивал). Если вы заботитесь только о завершении процесса, а не о его выводе, тогда "spawn" будет вполне достаточно.
дочерний процесс, созданный spawn()
дочерний процесс, созданный exec()
-main.js (файл)
var {spawn, exec} = require('child_process');
// 'node' is an executable command (can be executed without a shell)
// uses streams to transfer data (spawn.stout)
var spawn = spawn('node', ['module.js']);
spawn.stdout.on('data', function(msg){
console.log(msg.toString())
});
// the 'node module.js' runs in the spawned shell
// transfered data is handled in the callback function
var exec = exec('node module.js', function(err, stdout, stderr){
console.log(stdout);
});
-module.js(baiscally возвращает сообщение каждую секунду в течение 5 секунд, чем выход)
var interval;
interval = setInterval(function(){
console.log( 'module data' );
if(interval._idleStart > 5000) clearInterval(interval);
}, 1000);
spawn()
возвращает module data
сообщений каждую 1 секунду в течение 5 секунд, поскольку данные "потоковые"exec()
возвращает module data module data module data module data module data
только одного сообщения через 5 секунд (когда процесс закрыт), потому что данные "буферизируются" Обратите внимание, что ни дочерние процессы spawn()
ни дочерние процессы exec()
не предназначены для запуска модулей узлов, эта демонстрация предназначена только для демонстрации различия (если вы хотите запускать модули узлов, поскольку дочерние процессы используют вместо этого метод fork()
)
Наиболее существенное различие между child_process.spawn и child_process.exec заключается в том, что они возвращают - spawn возвращает поток, а exec возвращает буфер.
child_process.spawn возвращает объект с потоками stdout и stderr. Вы можете нажать на поток stdout, чтобы прочитать данные, которые дочерний процесс отправляет обратно в Node. stdout, являющийся потоком, имеет "данные", "конец" и другие события, которые имеют потоки. spawn лучше всего использовать, когда вы хотите, чтобы дочерний процесс возвращал большой объем данных в Node - обработка изображений, чтение двоичных данных и т.д.
child_process.spawn является "асинхронно асинхронным", что означает, что он начинает отправлять данные из дочернего процесса в потоке, как только дочерний процесс начинает выполняться.
child_process.exec возвращает весь буферный вывод дочернего процесса. По умолчанию размер буфера установлен на 200k. Если дочерний процесс возвращает что-то большее, ваша программа завершится сбоем с сообщением об ошибке "Ошибка: превышен maxBuffer". Вы можете решить эту проблему, установив больший размер буфера в параметрах exec. Но вы не должны этого делать, потому что exec не предназначен для процессов, которые возвращают ОГРОМНЫЕ буферы в Node. Вы должны использовать Spawn для этого. Так для чего вы используете exec? Используйте его для запуска программ, которые возвращают статусы результатов, а не данные.
child_process.exec является "синхронно асинхронным", то есть, хотя exec асинхронный, он ожидает завершения дочернего процесса и пытается вернуть все буферизованные данные одновременно. Если размер буфера exec не установлен достаточно большим, он завершается с ошибкой "maxBuffer Превышен".