Node多进程开发入门

Node子进程官方文档

我们在child_process中创建的进程就是Node.js的子进程;

child_process的用法:

异步:

  • exec
  • execFile
  • fork
  • spawn

同步:

  • execSync
  • execFileSync
  • spawnSync
js 复制代码
const cp = require("child_process");

child_process打印出的结果如下, 它提供了以下多种api:

异步方法

exec

exec主要是用来执行shell脚本的,exec支持3个参数command,options,callback;otpions有如下一些变量;

cwd的用法,指向上级路径,因为上级路径没有node_modules,所以不会打印出任何信息:

js 复制代码
cp.exec(
  path.resolve(__dirname, "test.shell"),
  {
    cwd: path.resolve("../"),
  },
  function (err, stdout, stderr) {
    console.log(err);
    console.log(stdout);
    console.log(stderr);
  }
);
js 复制代码
`child_process.exec(command, [options], [callback])`

我们可以通过ls打印当前文件夹的信息;

js 复制代码
// 用来执行shell脚本的
cp.exec("ls -al", function (err, stdout, stderr) {
  console.log(err);
  console.log(stdout);
  console.log(stderr);
});

err表示异常,stdout是正常执行的输出结果,stderr是异常时的输出结果;

exec加上管道符grep打印出node_modules的文件记录;

js 复制代码
// 管道符, 筛选出node_modules
cp.exec("ls -al|grep node_modules", function (err, stdout, stderr) {
  console.log(err);
  console.log(stdout);
  console.log(stderr);
});

exec也支持执行文件, 但不支持传参;

js 复制代码
// exec也支持执行文件,但不支持传参
cp.exec(path.resolve(__dirname, "test.shell"), function (err, stdout, stderr) {
  console.log(err);
  console.log(stdout);
  console.log(stderr);
});

execFile

execFile是用来执行一个文件;下面的例子ls也是指向一个文件bin/ls, execFile第二个参数是数组["-al"],它的回调函数和exec相同的;

js 复制代码
cp.execFile("ls", ["-al"], function (err, stdout, stderr) {
  console.log(err);
  console.log(stdout);
  console.log(stderr);
});

execFile中不能直接使用管道符grep,正确打开方式是shell脚本中写grep; 新建一个test.shell文件,echo $1是打印第一个参数;

js 复制代码
ls -al|grep node_modules

echo $1
js 复制代码
// __dirname是绝对路径
cp.execFile(
  path.resolve(__dirname, "test.shell"),
  ["-al"],
  function (err, stdout, stderr) {
    console.log(err);
    console.log(stdout);
    console.log(stderr);
  }
);

这时会报错,对test.shell文件得加上可执行权限;

js 复制代码
chmod =x bin/process/test.shell 
ll bin/process/test.shell

spawn

spawn支持的参数file, args入参,options;spawn没有回调;

js 复制代码
`child_process.spawn(command, [args], [options])`

spawn实现回调和打印报错;

js 复制代码
const child = cp.spawn(path.resolve(__dirname, "test.shell"), ["-al"], {
  cwd: path.resolve(".."),
});

child.stderr.on("data", function (chunk) {
  console.log("stderr--->", chunk.toString());
});

child.stdout.on("data", function (chunk) {
  console.log("stdout-->", chunk.toString());
});

spawn和exec、execFile的区别

spawn和exec、execFile都是异步执行;区别是:spawn是流式执行方式,它更适合耗时的执行任务,比如:npm的install,需要不断打印日志的;exec、execFile更是和开销比较小的任务;

js 复制代码
cnpm i -S urllib axios pkg-dir path-exists fs-extra commander npminstall user-home yargs

spawn执行cnpm install,一行行打印执行结果:

js 复制代码
const child = cp.spawn("cnpm", ["install"], {
  cwd: path.resolve("/Users/Minjie/Documents/vue3/mj-cli-new"),
});

child.stderr.on("data", function (chunk) {
  console.log(chunk.toString());
});

child.stdout.on("data", function (chunk) {
  console.log(chunk.toString());
});

用exec实现cnpm install,一次性打印出来所有结果:

js 复制代码
cp.exec(
  "cnpm install",
  { cwd: path.resolve("/Users/Minjie/Documents/vue3/mj-cli-new") },
  function (err, stdout, stderr) {
    console.log(err);
    console.log(stdout);
    console.log(stderr);
  }
);

fork

fork使用Node执行命令;

创建一个child.js文件;

js 复制代码
console.log("child process");

console.group("child pid:", process.pid);

类似于require;

js 复制代码
cp.fork(path.resolve(__dirname, "child.js"));

console.log("main pid:", process.pid);

fork和require的区别是主进程的pid和child pid不同,fork会启动子进程;

主进程和子进程可以进行通信;

js 复制代码
const child = cp.fork(path.resolve(__dirname, "child.js"));
child.send("hello child process", () => {
  // 断开
  child.disconnect();
});
console.log("main pid:", process.pid);

child.js

js 复制代码
console.log("child process");

console.group("child pid:", process.pid);

// 监听
process.on("message", (msg) => {
  console.log("msg:", msg);
});

fork适用于耗时的操作,比如下载文件;

同步方法

execSync、execFileSync

execSync打印结果不再需要回调函数,使用简单,适用于简单命令;execSync有一个隐患就是对命令的安全没有做校验;

js 复制代码
const ret = cp.execSync("ls -al|grep node_modules");
console.log("ret:", ret.toString());

const ret2 = cp.execFileSync("ls", ["-al"]);
console.log("ret2:", ret2.toString());

const ret3 = cp.spawnSync("ls", ["-al"]);
console.log("ret3:", ret3.output.toString());
相关推荐
yddddddy1 小时前
css的基本知识
前端·css
昔人'1 小时前
css `lh`单位
前端·css
Nan_Shu_6143 小时前
Web前端面试题(2)
前端
知识分享小能手3 小时前
React学习教程,从入门到精通,React 组件核心语法知识点详解(类组件体系)(19)
前端·javascript·vue.js·学习·react.js·react·anti-design-vue
蚂蚁RichLab前端团队4 小时前
🚀🚀🚀 RichLab - 花呗前端团队招贤纳士 - 【转岗/内推/社招】
前端·javascript·人工智能
孩子 你要相信光4 小时前
css之一个元素可以同时应用多个动画效果
前端·css
huangql5204 小时前
npm 发布流程——从创建组件到发布到 npm 仓库
前端·npm·node.js
Days20504 小时前
LeaferJS好用的 Canvas 引擎
前端·开源
小白菜学前端5 小时前
vue2 常用内置指令总结
前端·vue.js
林_深时见鹿5 小时前
Vue + ElementPlus 自定义指令控制输入框只可以输入数字
前端·javascript·vue.js