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());
相关推荐
柒和远方9 分钟前
V043:BFF 层流式输出:从前端直连到生产级流式网关的架构演进
javascript·架构·node.js
不简说36 分钟前
JS 代码技巧 vol.4 — 10 个异步并发控制,Promise.all 这帮兄弟的踩坑实录
前端·javascript·面试
Sinclair1 小时前
安企CMS的安装-PHPStudy(小皮面板)部署
前端·后端
会飞的特洛伊1 小时前
IAM身份认证
前端·后端
钛态2 小时前
AI 组件生成评测:别只看页面能不能渲染
前端·vue·react·web
Hyyy2 小时前
requestAnimationFrame和setTimeout有什么不同
前端
Jackson__2 小时前
问到你想清楚,这个 skill 专治没想明白就写代码!
前端·github·ai编程
এ慕ོ冬℘゜2 小时前
前端实战:Textarea 实时字数计数输入器(带字数限制+UI优化完整源码)
前端·ui
程序员黑豆3 小时前
从零开始:创建第一个鸿蒙应用程序
前端·harmonyos
只与明月听4 小时前
LangChain 学习-掌握LangChain Core API
前端·人工智能·后端