Node.js 重生与处决

Node.js Spawn vs. Execute

在我正在观看的学习 Node 的在线培训视频中,旁白说 "spawn is better for longer processes involving large amounts of data, whereas execute is better for short bits of data."

这是为什么? Node.js 中的 child_process spawn 和 execute 函数有什么区别,我什么时候知道该使用哪一个?

一个好的起点是 NodeJS documentation

对于 'spawn' 文档状态:

The child_process.spawn() method spawns a new process using the given command, with command line arguments in args. If omitted, args defaults to an empty array.

同时 'exec':

Spawns a shell then executes the command within that shell, buffering any generated output. The command string passed to the exec function is processed directly by the shell and special characters (vary based on shell) need to be dealt with accordingly.

主要是你是否需要处理命令的输出,我想这可能是影响性能的因素(我没有比较过)。如果您只关心流程完成,那么 'exec' 将是您的选择。 Spawn 使用 ondata 事件为 stdout 和 stderr 打开流,只执行 returns 一个缓冲区,其中 stdout 和 stderr 作为字符串。

主要的区别是spawn更适合长时间运行输出量大的过程。 spawn 流 input/output 与子进程。 exec 在一个小的(默认为 200K)缓冲区中缓冲输出。另外据我所知 exec 首先生成子 shell,然后尝试执行您的进程。长话短说,如果您需要从子进程流式传输大量数据,请使用 spawn;如果您需要 shell 管道、重定向甚至需要 exec 等功能,请使用 exec一次一个节目。

一些有用的链接 - DZone Hacksparrow

  • 子进程由 spawn()

    创建
    • 不会产生 shell
    • 流式传输子进程返回的数据(数据流是恒定的)
    • 没有数据传输大小限制
  • 子进程由 exec()

    创建
    • 确实会生成一个 shell 并在其中执行传递的命令
    • 缓冲数据(等到进程关闭并在块上传输数据)
    • 最大数据传输到 Node.js v.12.x 为 200kb(默认),但自从 Node.js v.12x 增加到 1MB(默认)

-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(基本上 returns 每秒一条消息,持续 5 秒然后退出)

var interval;
interval = setInterval(function(){
    console.log( 'module data' );
    if(interval._idleStart > 5000) clearInterval(interval);
}, 1000);
  • spawn()子进程returns消息module data每1秒5秒,因为数据是'streamed'
  • exec()子进程returns只有一条消息module data module data module data module data module data5秒后(当进程关闭时)这是因为数据是'buffered'

注意 spawn()exec() 子进程都不是为 运行ning 节点模块设计的,这个演示只是为了展示差异,(如果你想 运行 节点模块作为子进程使用 fork() 方法代替)

引自官方文档:

For convenience, the child_process module provides a handful of synchronous and asynchronous alternatives to child_process.spawn() and child_process.spawnSync(). Each of these alternatives are implemented on top of child_process.spawn() or child_process.spawnSync().