Node子进程进阶

最近在做12306爬虫,刚好遇到了Node子进程的应用场景,不总结不快:

const { spawn, exec, execFile ,fork } = require('child_process');

Node的child_process模块提供了衍生子进程的功能,通常子进程开启后,会与父进程建立 stdinstdoutstderr 的管道。如上代码所示,child_process模块暴露了4个方法,其中spawn为“根本大法”,其余的3个均在其基础上衍生而来,而每个方法都有同步和异步两个版本,本文主要以异步方法为主,因为结合Node单线程和12306爬虫这个web应用来说,谈论异步场景更为合适。

spawn(command[, args][, options])

#运行 ls -lh /usr,并捕获 stdout、stderr、以及退出码(取自Node官网)
const { spawn } = require('child_process');
const ls = spawn('ls', ['-lh', '/usr']);

ls.stdout.on('data', (data) => {
  console.log(`stdout: ${data}`);
});

ls.stderr.on('data', (data) => {
  console.log(`stderr: ${data}`);
});

ls.on('close', (code) => {
  console.log(`子进程退出码:${code}`);
});

exec(command[, options][, callback])

此方法生成一个 shell 并在 shell 中执行 command

const { exec } = require('child_process');
exec('cat *.js missing_file | wc -l', (error, stdout, stderr) => {
  if (error) {
    console.error(`执行出错: ${error}`);
    return;
  }
  console.log(`stdout: ${stdout}`);
  console.log(`stderr: ${stderr}`);
});

execFile(file[, args][, options][, callback])

本方法与exec()类似,只是不衍生 shell。 file脚本文件会被直接衍生为一个新进程,这使得它比 child_process.exec() 更高效

const { execFile } = require('child_process');
const child = execFile('node', ['--version'], (error, stdout, stderr) => {
  if (error) {
    throw error;
  }
  console.log(stdout);
});

可以使用util.promisify()进行Promise化:

const util = require('util');
const execFile = util.promisify(require('child_process').execFile);
async function getVersion() {
  const { stdout } = await execFile('node', ['--version']);
  console.log(stdout);
}
getVersion();

fork(modulePath[, args][, options])

fork()方法用于专门衍生新的 Node.js 进程,衍生的 Node.js 子进程与两者之间建立的 IPC 通信信道的异常是独立于父进程的。 每个进程都有自己的内存,使用自己的 V8 实例。 由于需要额外的资源分配,因此不建议衍生大量的 Node.js 进程。spawn ()方法的一种特殊情况。

总结

spawn(), exec(), execFile() ,fork()都遵循 Node.js 惯用的异步编程模式。每个方法都返回 ChildProcess实例。这些对象都实现了 EventEmitter接口,允许父进程注册监听器函数,在子进程生命周期期间,当特定的事件(close/disconnect/error/exit/message)发生时会调用这些函数。
其中,exec()execFile() 可以额外指定 callback 函数,当子进程结束时会被调用。

你可能感兴趣的:(Node子进程进阶)