我正在观看一段在线的Node.js培训视频,视频中的讲解者提到:"对于需要处理大量数据的长时间运行的进程,使用spawn更好,而对于短小精悍的数据,则使用execute更合适。"
这是为什么呢?child_process模块中的spawn和execute函数有什么区别?在何时应该选择它们中的哪一个?
我正在观看一段在线的Node.js培训视频,视频中的讲解者提到:"对于需要处理大量数据的长时间运行的进程,使用spawn更好,而对于短小精悍的数据,则使用execute更合适。"
这是为什么呢?child_process模块中的spawn和execute函数有什么区别?在何时应该选择它们中的哪一个?
spawn
更适合于具有大量输出的长时间运行进程。这是因为 spawn
使用子进程流式输入/输出。另一方面,exec
在一个小型缓冲区(默认情况下为1MB,在 v11.x 版本之前为 200 KB)中缓存输出。 exec
首先生成一个子 shell,然后尝试执行您的进程。简而言之,如果您需要从子进程流式传输大量数据,请使用 spawn
;如果您需要 shell 管道、重定向甚至同时运行多个程序等功能,请使用 exec
。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(基本上每秒返回一条消息,持续5秒钟,然后退出)
var interval;
interval = setInterval(function(){
console.log( 'module data' );
if(interval._idleStart > 5000) clearInterval(interval);
}, 1000);
spawn()
子进程每1秒返回一条消息 module data
,持续5秒,因为数据是“流式”的。exec()
子进程在5秒后(进程关闭时)只返回一条消息:module data module data module data module data module data
。这是因为数据是“缓冲”的。请注意,无论是 spawn()
还是 exec()
子进程都不是设计用于运行 Node 模块的,这个示例只是为了展示它们之间的区别。(如果你想要运行 Node 模块作为子进程,请使用 fork()
方法。)
var spawn = spawn(...)
和 var exec = exec(...)
这样的写法,因为这会覆盖函数。 - Remirrorspawn
可以运行一个shell。请参见:https://nodejs.org/api/child_process.html#child_processspawncommand-args-options - MichaelMoser一个很好的开始是阅读NodeJS 文档。
关于'spawn',文档表明:
child_process.spawn()方法使用给定的命令生成一个新进程,并在args中传递命令行参数。如果省略,则args默认为空数组。
而对于'exec':
生成一个Shell,然后在该Shell中执行命令,缓冲所有生成的输出。 exec函数传递给命令字符串直接由shell处理,特殊字符(根据shell的不同)需要相应地处理。
主要问题似乎在于您是否需要处理命令的输出,这可能会影响性能(我还没有进行比较)。 如果您只关心进程完成,则应选择'exec'。 Spawn打开stdout和stderr的ondata事件流,而exec仅以字符串形式返回stdout和stderr的缓冲区。
来自官方文档的一句话:
为了方便起见,
child_process
模块提供了一些同步和异步的选项来替代child_process.spawn()
和child_process.spawnSync()
。每个选项都是基于child_process.spawn()
或child_process.spawnSync()
实现的。
exec
和spawn
都返回ChildProcess
对象。文档说spawn
流式传输stdout
,而exec
则将其缓冲,所以我尝试了这个:cp.stdout.on("data", ...)
,其中cp
是由exec
返回的。结果发现数据也是一块一块地流出来的。我有点困惑。 - Zhouexec
返回的 ChildProcess 对象,类似于使用spawn
,但这有点违背了使用exec
的初衷,因为该函数抽象了处理流的需要。然而,在幕后这些流仍然存在,exec
只是帮你收集了它们的数据。你发现的只是在使用exec
时那些流仍然对你可用。然而,通常没有真正需要使用它们。 - Thomas Watson