关于前端:学习笔记childprocess

69次阅读

共计 4724 个字符,预计需要花费 12 分钟才能阅读完成。

child_process

child_process 用于创立衍生子过程。Node 和衍生的子过程建设 stdin(规范输出), stdout(规范输入), stderr(规范谬误) 管道。child_process.spawn, child_process.fork, child_process.exec, child_process.execFile 都会返回 ChildProcess 实例。ChildProcess 实例实现了 EventEmitter API,能够在子过程实例上增加事件的回调函数。过程之间能够通过事件音讯零碎进行相互通信。

child_process.spawn

启动一个子过程,执行命令。spawn 的接口定义: spawn(command: string, args: ReadonlyArray<string>, options: SpawnOptions): ChildProcess

  • command, 须要运行的命令
  • args, 运行命令的参数, 是一个字符串数组
  • options, 配置项

    • options.cwd 子过程的工作目录
    • options.env 环境变量, 应用 key, value 配置环境变量
    • 等等
  • 返回值 ChildProcess, 返回 ChildProcess 的实例
// 例子
const {spawn, spawnSync} = require('child_process')
const path = require('path')

const cp = spawn('ls', ['-a'], {cwd: path.resolve(__dirname, '../Movies')
})

cp.stdout.on('data', (data) => {console.log(` 子过程输入:' ${data}`)
})

cp.on('exit', (code, signal) => {console.log('子过程退出:', `code ${code} and signal ${signal}`)
})

输入后果:

默认状况下,子过程的规范输出、规范输入和规范谬误被重定向到 ChildProcess 对象上相应的 subprocess.stdin, subprocess.stdout 和 subprocess.stderr 流。能够设置 options.stdio: inherit, 传入父过程,

const {spawn, spawnSync} = require('child_process')
const path = require('path')

const cp = spawn('ls', ['-a'], {cwd: path.resolve(__dirname, '../Movies'),
  stdio: 'inherit'
})

child_process.spawnSync

child_process.spawn 的同步版本。child_process.spawnSync 返回 Object。Object 蕴含了: pid(子过程 pid), stdout(规范输入), stderr(规范谬误) 等等。不同之处在于该函数在子过程齐全敞开之前不会返回。

const {spawnSync} = require('child_process')
const path = require('path')


const obj = spawnSync('ls', ['-a'],{cwd: path.resolve(__dirname, '../Movies') })

console.log('pid', `${obj.pid}`)
console.log('stdout', `${obj.stdout}`)

child_process.exec

创立一个衍生的 shell, 而后能够在衍生的 shell 之中执行命令。exec 实现了函数重载。第二个参数能够是配置项,或者是 callback。如果第二个参数是配置项,那么第三个参数就是 callback。

const {exec} = require('child_process')
const path = require('path')

exec('ls', (error, stdout, stderr) => {if (error) {console.error('error:', error);
    return;
  }
  console.log('stdout:' + stdout);
  console.log('stderr:' + stderr);
})

// 第二个参数能够是配置项
exec('ls -a', { cwd: path.resolve(__dirname, '../Movies'), }, (error, stdout, stderr) => {if (error) {console.error('error:', error);
    return;
  }
  console.log('stdout:' + stdout);
  console.log('stderr:' + stderr);
})

callback 的三个参数别离是谬误实例(如果执行胜利, error 等于 null), stdout 规范输入, stderr 规范谬误。

child_process.execSync

child_process.exec 的同步版本。child_process.execSync 办法返回规范输入,不同之处在于该办法在子过程齐全敞开之前不会返回。

const {execSync} = require('child_process')
const path = require('path')

const stdout = execSync('ls -a', { cwd: path.resolve(__dirname, '../Movies') })

console.log('stdout:', `${stdout}`)

child_process.exec 和 child_process.spawn 区别

  • spawn

    1. 不会创立衍生的 shell
    2. 流式的传输子过程产生的数据
    3. 没有数据大小的限度
  • exec

    1. 会创立衍生的 shell
    2. 最大传输 200kb 的数据
    3. 会缓存数据, 过程敞开后传输数据

spawn 适宜微小长时间的传输数据。exec 适宜须要屡次,小量的状况。

child_process.fork

child_process.fork, 用于在子过程中运行模块。child_process.fork(modulePath [, args] [, options])

  • modulePath, 须要在子过程中运行的模块地址
  • args, 字符串参数列表
  • options 配置项

    • execPath, 用来创立子过程的可执行文件。咱们能够通过配置这个参数,指定不同版本的 node 创立子过程。
    • execArgv, 传给可执行文件的字符串参数列表。
    • silent, 子过程的规范输入, 是否从父过程进行继承。默认是 false 进行继承。如果设置为 true 则间接 pipe 向子过程的 child.stdin, child.stdout 等。
    • stdio, 用于配置在父过程和子过程之间建设的管道
// 子过程的代码
console.log('我是子过程')
const {fork} = require('child_process')
const {resolve} = require('path')

// 我是子过程
fork(resolve(__dirname, './cp.js'), {silent: false})

// 没有打印
fork(resolve(__dirname, './cp.js'), {silent: true})
const {fork} = require('child_process')
const {resolve} = require('path')

const cp = fork(resolve(__dirname, './cp.js'), {silent: true})

cp.stdout.on('data', function (data) {
  // stdout 中输入:我是子过程
  console.log('stdout 中输入:', `${data}`)
})

通过 stdout 属性,能够获取到子过程输入的内容

child_process.execFile

child_process.execFile 不会创立衍生的 shell。效率要比 exec 要高。child_process.execFile(file[, args] [, options] [, callback])

  • file, 能够是执行文件的名字,或者门路。
const {execFile} = require('child_process')
const {resolve} = require('path')

execFile('node', [resolve(__dirname, './cp.js')], (err, stdout, stderr) => {if (err) {throw err}
  console.log(`stdout: ${stdout}`)
})

child_process.exec 和 child_process.execFile 的区别

exec 外部通过调用 execFile 来实现。而 execFile 外部通过调用 spawn 来实现。

事件

ChildProcess 实例上能够监听很多事件

  • close, 子过程的 stdio 流敞开时触发
  • disconnect, 父过程手动调用 child.disconnect 函数时触发
  • error, 产生谬误时会触发
  • exit, 子过程退出时触发
  • message, 子过程应用 process.send 函数来传递音讯时触发
const {fork} = require('child_process');

const cp = fork('./cp.js')

cp.on('close', (code, signal) => {console.log('close 事件:', code, signal);
})

cp.on('disconnect', () => {console.log('disconnect 事件...');
})

cp.on('error', (code, signal) => {console.log('error 事件:', code, signal);
})

cp.on('exit', (code, signal) => {console.log('exit 事件:', code, signal);
})

cp.on('message', (val) => {console.log('message 事件:', val);
})

过程之间的通信

创立子过程后, 父过程与子过程之间将会创立 IPC 通道,父子过程之间通过 message 和 send 来通信。

// 父过程
const {fork} = require('child_process');

const cp = fork('./cp.js')

cp.on('message', (msg) => {console.log('message:' + JSON.stringify(msg))
})
// 子过程
process.send({msg: '我是子过程'})

父过程也能够向子过程发送音讯应用 cp.send

// 父过程
const {fork} = require('child_process');

const cp = fork('./cp.js')

cp.send({msg: '我是父过程'})

参考

  • Node.js v16.8.0 文档
  • Node.js Child Processes: Everything you need to know
  • exec vs execFile nodeJs
  • Node.js Spawn vs. Execute
  • Nodejs 进阶:如何玩转子过程(child_process)
  • 深刻了解 Node.js 中的过程与线程
  • Node.js process 模块学习指南
  • 玩转 node 子过程 — child_process

正文完
 0