17. 扩展应用程序

Node.js以单线程模式运行,但它使用事件驱动的范例来处理并发。 它还有助于创建子进程,以便在基于多核CPU的系统上利用并行处理。

子进程总是有三个流child.stdinchild.stdoutchild.stderr ,它们可以与父进程的stdio流共享。

Node提供了child_process 模块,该模块具有以下三种创建子进程的主要方法。

  • exec – child_process.exec方法在shell /控制台中运行命令并缓冲输出。
  • spawn – child_process.spawn使用给定命令启动新进程。
  • fork – child_process.fork方法是 spawn() 创建子进程的特例。

17.1. exec() 方法

  • child_process.exec 方法在shell中运行命令并缓冲输出。 它有以下签名:
    child_process.exec(command[, options], callback)
    
  • 参数:
    • command (String)要使用以空格分隔的参数运行的命令
    • options (Object)可能包含以下一个或多个选项 –
      • cwd (String)子进程的当前工作目录
      • env (Object)环境键值对
      • encoding (String)(默认值:’utf8’)
      • shell (String)用于执行命令的Shell(UNIX上的默认:’/ bin/sh’,Windows上的’cmd.exe’,shell应该理解UNIX上的-c开关或Windows上的/ s/c。在Windows上,命令行解析应该与cmd.exe兼容。)
      • timeout (数字)(默认值:0)
      • maxBuffer (Number)(默认值:200 * 1024)
      • killSignal (String)(默认值:’SIGTERM’)
      • uid (Number)设置进程的用户标识。
      • gid (Number)设置进程的组标识。
    • callback 该函数获取三个参数errorstdout,stderr ,它们在进程终止时使用输出调用。
  • exec() 方法返回一个具有最大大小的缓冲区,并等待进程结束并尝试一次返回所有缓冲的数据。

17.2. 示例

  • 让我们创建两个名为support.js和master.js的js文件:
  • File: support.js
    console.log("Child Process " + process.argv[2] + " executed." );
    
  • File: master.js
    const fs = require('fs');
    const child_process = require('child_process');
    for(var i=0; i<3; i++) {
       var workerProcess = child_process.exec('node support.js '+i,function 
          (error, stdout, stderr) {
          if (error) {
             console.log(error.stack);
             console.log('Error code: '+error.code);
             console.log('Signal received: '+error.signal);
          }
          console.log('stdout: ' + stdout);
          console.log('stderr: ' + stderr);
       });
       workerProcess.on('exit', function (code) {
          console.log('Child process exited with exit code '+code);
       });
    }
    
  • 现在运行master.js来查看结果:$ node master.js。验证输出:
    Child process exited with exit code 0
    stdout: Child Process 1 executed.
    stderr:
    Child process exited with exit code 0
    stdout: Child Process 0 executed.
    stderr:
    Child process exited with exit code 0
    stdout: Child Process 2 executed.
    

17.3. spawn() 方法

  • child_process.spawn方法使用给定命令启动新进程。 它有以下签名:
    child_process.spawn(command[, args][, options])
    
  • 参数:
    • command (String)要运行的命令
    • args (Array)字符串参数列表
    • options (Object)可能包含以下一个或多个选项 –
      • cwd (String)子进程的当前工作目录。
      • env (Object)环境键值对。
      • stdio (Array)String Child的stdio配置。
      • customFds (Array)已弃用的子文件描述符,用于stdio。
      • detached (布尔值)子将成为进程组的领导者。
      • uid (Number)设置进程的用户标识。
      • gid (Number)设置进程的组标识。
  • spawn() 方法返回流(stdout和stderr),当进程返回大量数据时应该使用它。 一旦进程开始执行,spawn() 就开始接收响应。

17.4. 示例

  • 创建两个名为support.js和master.js的js文件:
  • File: support.js
    console.log("Child Process " + process.argv[2] + " executed." );
    
  • File: master.js
    const fs = require('fs');
    const child_process = require('child_process');
    for(var i = 0; i<3; i++) {
       var workerProcess = child_process.spawn('node', ['support.js', i]);
       workerProcess.stdout.on('data', function (data) {
          console.log('stdout: ' + data);
       });
       workerProcess.stderr.on('data', function (data) {
          console.log('stderr: ' + data);
       });
       workerProcess.on('close', function (code) {
          console.log('child process exited with code ' + code);
       });
    }
    
  • 现在运行master.js来查看结果:$ node master.js。验证输出:
    stdout: Child Process 0 executed.
    child process exited with code 0
    stdout: Child Process 1 executed.
    stdout: Child Process 2 executed.
    child process exited with code 0
    child process exited with code 0
    

17.5. fork() 方法

  • child_process.fork方法是 spawn() 创建Node进程的特例。 它有以下签名:
    child_process.fork(modulePath[, args][, options])
    
  • 参数:
    • modulePath (String)要在子级中运行的模块。
    • args (Array)字符串参数列表
    • options (Object)可能包含以下一个或多个选项 –
      • cwd (String)子进程的当前工作目录。
      • env (Object)环境键值对。
      • execPath (String)用于创建子进程的可执行文件。
      • execArgv (Array)传递给可执行文件的字符串参数列表(默认值:process.execArgv)。
      • silent (布尔值)如果为true,则子节点的stdin,stdout和stderr将通过管道输送到父节点,否则它们将从父节点继承,请参阅spawn()的stdio的“管道”和“继承”选项更多细节(默认为false)。
      • uid (Number)设置进程的用户标识。
      • gid (Number)设置进程的组标识。
  • 除了在普通的ChildProcess实例中具有所有方法之外,fork方法还返回具有内置通信通道的对象。

17.6. 示例

  • 创建两个名为support.js和master.js的js文件:
  • File: support.js
    console.log("Child Process " + process.argv[2] + " executed." );
    
  • File: master.js
    const fs = require('fs');
    const child_process = require('child_process');
    for(var i=0; i<3; i++) {
       var worker_process = child_process.fork("support.js", [i]);
       worker_process.on('close', function (code) {
          console.log('child process exited with code ' + code);
       });
    }
    
  • 现在运行master.js来查看结果:$ node master.js。验证输出:
    Child Process 0 executed.
    Child Process 1 executed.
    Child Process 2 executed.
    child process exited with code 0
    child process exited with code 0
    child process exited with code 0
    
下一节:JXcore:是一个开源项目,它引入了一个独特的功能,用于将源文件和其他资产打包和加密到JX包中。