child_process 這個(gè)模塊非常重要蕊爵。掌握了它,等于在node的世界開(kāi)啟了一扇新的大門浦楣。
創(chuàng)建異步進(jìn)程
四個(gè)方法
以下四個(gè)方法均返回 ChildProcess 的實(shí)例
- exec
語(yǔ)法:child_process.exec(command[, options][, callback])
注意:
1限煞、command 是一個(gè) shell 命令的字符串障本,包含了命令的參數(shù)
2弛槐、可以使用 callback懊亡;
3、衍生一個(gè) shell 然后在該 shell 中執(zhí)行 command乎串,command 一般是 shell 內(nèi)置的 命令店枣,如 ls,cat 等,也可以是shell腳本組成的文件,如 start.sh 等
// 回調(diào)函數(shù)版
const { exec } = require('child_process');
exec('cat *.js missing_file | wc -l', (error, stdout, stderr) => {
if (error) {
console.error(`執(zhí)行出錯(cuò): ${error}`);
return;
}
console.log(`stdout: ${stdout}`);
console.log(`stderr: ${stderr}`);
});
// promise 版
const util = require('util');
const exec = util.promisify(require('child_process').exec);
async function lsExample() {
const { stdout, stderr } = await exec('cat *.js missing_file | wc -l');
console.log('stdout:', stdout);
console.log('stderr:', stderr);
}
lsExample();
- execFile
語(yǔ)法:child_process.execFile(file[, args][, options][, callback])
注意:
1鸯两、與 exec 的不同是坏瞄,命令的參數(shù)不能放在第一個(gè)參數(shù),只能作為第二個(gè)參數(shù)傳遞甩卓;
2、默認(rèn)情況下不會(huì)衍生 shell蕉斜,指定的可執(zhí)行 file 直接作為新進(jìn)程衍生逾柿,使其比 child_process.exec() 稍微更高效
3、file 是要運(yùn)行的可執(zhí)行文件的名稱或路徑宅此,如 node.exe机错,不能是 start.js 這種腳本文件
// 回調(diào)函數(shù)版
const { execFile } = require('child_process');
const child = execFile('node', ['--version'], (error, stdout, stderr) => {
if (error) {
throw error;
}
console.log(stdout);
});
// 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
語(yǔ)法:child_process.fork(modulePath[, args][, options])
注意:
1、該接口專門用于衍生新的 Node.js 進(jìn)程
2父腕、modulePath 是要在node子進(jìn)程中運(yùn)行的模塊弱匪,由于是 node.js 的進(jìn)程,所以可以是 start.js 這種 js 文件
3璧亮、無(wú)回調(diào)萧诫,參數(shù)要以第二個(gè)參數(shù)傳入
4、返回的子進(jìn)程將內(nèi)置一個(gè)額外的ipc通信通道枝嘶,允許消息在父進(jìn)程和子進(jìn)程之間來(lái)回傳遞帘饶。
// IPC 通道
// parent.js
var child_process = require('child_process');
var child = child_process.fork('./child.js');
child.on('message', function(m){
console.log('message from child: ' + JSON.stringify(m));
});
child.send({from: 'parent'});
// child.js
process.on('message', function(m){
console.log('message from parent: ' + JSON.stringify(m));
});
process.send({from: 'child'});
// 運(yùn)行 node parent.js的 result
message from child: {"from":"child"}
message from parent: {"from":"parent"}
- spawn
語(yǔ)法:child_process.spawn(command[, args][, options])
注意:使用給定的 command 衍生一個(gè)新進(jìn)程,并帶上 args 中的命令行參數(shù)群扶。
var spawn = require('child_process').spawn;
var child = spawn('bad_command');
child.on('error', (err) => {
console.log('Failed to start child process 1.');
});
var child2 = spawn('ls', ['nonexistFile']);
child2.stderr.on('data', function(data){
console.log('Error msg from process 2: ' + data);
});
child2.on('error', (err) => {
console.log('Failed to start child process 2.');
});
四個(gè)方法的區(qū)別
主要的區(qū)別在于第一個(gè)參數(shù)的含義不同:
對(duì)于 exec 和 execFile 傳遞的是 command 或 可執(zhí)行文件及刻,類似 ls 或者 start.sh 或者 node;可接受回調(diào); 二者不同的是命令的參數(shù)位置
對(duì)于 fork 傳遞的是node支持的腳本,類似 start.js竞阐,無(wú)回調(diào)
對(duì)于 spawn缴饭,它是以上三個(gè)方法實(shí)現(xiàn)的基礎(chǔ)。
對(duì)于構(gòu)建開(kāi)發(fā)環(huán)境而言骆莹,一般至少會(huì)起兩個(gè)進(jìn)程颗搂,主進(jìn)程起 devServer;還需一個(gè)進(jìn)程起mock API 服務(wù)器汪疮,所以一般用 fork 較多
var fork = require('child_process').fork;
// ...省略 sass 任務(wù)
gulp.task('dev-server',function(){
gulpLivereload.listen();
gulp.watch('./public/scss/*.scss', gulp.series(['sass']));
fork('./server.js')
})
gulp.task('default', gulp.series(['sass','dev-server']));
// fork('./server.js') 還可以用這樣替換
exec('node ./server.js',(err,stdout,stderr)=>{
if (err) {
console.log('err',err)
} else {
console.log('stdout',stdout)
}
})
// 或者
child.execFile('node', ['./server.js'],(err,stdout,stderr)=>{
if (err) {
console.log('err',err)
} else {
console.log('stdout',stdout)
}
})
然后一個(gè) gulp 命令就會(huì)啟動(dòng)兩個(gè)進(jìn)程
關(guān)于 ChildProcess 類
1峭火、ChildProcess
類的實(shí)例都是 EventEmitter
,表示衍生的子進(jìn)程
2智嚷、每個(gè)實(shí)例都有 stdout, stdin, stderr 三個(gè)流對(duì)象
3卖丸、通過(guò) fork 產(chǎn)生的子進(jìn)程與父進(jìn)程可以用 send 方法及監(jiān)聽(tīng) message 事件來(lái)相互通信
4、 幾個(gè)事件: error , message , exit , close , disconnect