美文网首页
Node学习指南

Node学习指南

作者: 小怪兽大作战 | 来源:发表于2021-04-01 20:41 被阅读0次

为什么要有Node子进程

node遵循的是单线程单进程的模式,node的单线程是指js的引擎只有一个实例,且在nodejs的主线程中执行。node的单线程使得在主线程不能进行cpu密集操作,否则会阻塞主线程。对于cpu密集型操作,在node中通过child_process可以创建独立的子进程。父子进程通过IPC通信,子进程执行后可以将结果返回给父进程。

node是严格单线程的吗

node不是严格的单线程,node中存在多个线程
js引擎执行的线程
定时器线程(setTimeout, setInterval)
异步http线程(ajax)

我们平时所说的单线程是指node中只有一个js引擎在主线程上运行。其他异步IO和事件驱动相关的线程通过libuv来实现内部的线程池和线程调度。libv中存在了一个Event Loop,通过Event Loop来切换实现类似于多线程的效果。简单的来讲Event Loop 就是维持一个执行栈和一个时间队列,当前执行栈中的如果发现异步IO以及定时器等函数,就会把这些异步会掉函数放入到事件队列中。当前执行栈执行完成后,从事件队列中,按照一定的顺序执行事件队列中的异步回调函数。

image.png

创建node子进程的四种方式

有四种方法创建node子进程,分别是spawn,execFile,exec,fork


image.png

上图可以展示出这4个方法的区别,我们也可以简要介绍这4中方法的不同。

spawn : 子进程中执行的是非node程序,提供一组参数后,执行的结果以流的形式返回。
execFile:子进程中执行的是非node程序,提供一组参数后,执行的结果以回调的形式返回。
exec:子进程执行的是非node程序,传入一串shell命令,执行后结果以回调的形式返回,与execFile不同的是exec可以直接执行一串shell命令。
fork:子进程执行的是node程序,提供一组参数后,执行的结果以流的形式返回,与spawn不同,fork生成的子进程只能执行node应用。

使用spwan创建子进程

使用child_process.spawn创建一个子进程,会返回一个带有stdout和stderr流的对象。你可以通过stdout流来读取子进程返回给Node.js的数据。stdout拥有’data’,’end’以及一般流所具有的事件。当想要子进程返回大量数据给Node时,比如说图像处理,读取二进制数据等等,最好使用spawn方法。


image.png

例子
创建子进程,并且通过子进程执行pwd命令

const { spawn } = require('child_process');
const child = spawn('pwd');
child.stdout.on('data', (data) => {
  console.log(`stdout: ${data}`);
});
child.stderr.on('data', (data) => {
  console.log(`stderr: ${data}`);
});

child.on('exit', function (code, signal) {
    console.log('child process exited with ' +
                `code ${code} and signal ${signal}`);
  });

使用exec创建子进程

exec方法接收要运行的命令,创建子进程并执行命令,最后将子进程的输出以回调函数参数的形式返回。


image.png

例子
使用exec创建子进程并执行pwd方法

require('child_process').exec('pwd', {encoding: ‘utf-8’}, function(err, stdout, stderr) {
    if (err) {
        console.log(error.stack);
        console.log('Error code: ' + error.code);
        console.log('Signal received: ' + error.signal);
    }
    //console.log(err, stdout, stderr);
    console.log('data : ' + stdout);
}).on('exit', function (code) {
    console.log('子进程已退出, 退出码 ' + code);
});

使用execFile创建子进程

execFile和exec功能大部分一样,区别是execFile输入一个文件,exec会创建一个shell,execFile会直接运行进程,这使得execFile比spawn和exec都高效。

例子
使用execFile创建子进程,并运行脚本文件
让我们创建两个 js 文件 support.js 和 master.js
support.js 代码

pwd

master.js代码

const child_process = require('child_process');
 
var workerProcess = child_process.exec('support.js ', 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('子进程已退出,退出码 '+code);
    });

fork方法

fork方法是spawn方法的特殊形式,主要区别是fork创建的子进程会和父进程之间建立通信管道,子进程可以通过send函数向父进程发送信息,父进程也可以通过send向子进程发送信息。

例子
父进程和子进程发送消息
父进程方法

const { fork } = require('child_process');

const forked = fork('child.js');

forked.on('message', (msg) => {
  console.log('Message from child', msg);
});

forked.send({ hello: 'world' });

子进程方法

process.on('message', (msg) => {
  console.log('Message from parent:', msg);
});

let counter = 0;

setInterval(() => {
  process.send({ counter: counter++ });
}, 1000);

相关文章

网友评论

      本文标题:Node学习指南

      本文链接:https://www.haomeiwen.com/subject/ujcxkltx.html