iis服务器助手广告广告
返回顶部
首页 > 资讯 > 前端开发 > JavaScript >Node.js中创建子进程的方法有哪些
  • 398
分享到

Node.js中创建子进程的方法有哪些

2024-04-02 19:04:59 398人浏览 独家记忆
摘要

这篇文章主要讲解了“node.js中创建子进程的方法有哪些”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“node.js中创建子进程的方法有哪些”吧!众所周知

这篇文章主要讲解了“node.js中创建子进程的方法有哪些”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“node.js中创建子进程的方法有哪些”吧!

Node.js中创建子进程的方法有哪些

众所周知,Node.js 是单线程、异步非阻塞的程序语言,那如何充分利用多核 CPU 的优势呢?这就需要用到 child_process 模块来创建子进程了,在 Node.js 中,有四种方法可以创建子进程:

  • exec

  • execFile

  • spawn

  • fork

上面四个方法都会返回 ChildProcess 实例(继承自 EventEmitter),该实例拥有三个标准的  stdio 流:

  • child.stdin

  • child.stdout

  • child.stderr

子进程生命周期内可以注册监听的事件有:

exit:子进程结束时触发,参数为 code 错误码和 signal 中断信号。

close:子进程结束并且 stdio 流被关闭时触发,参数同 exit 事件。

disconnect:父进程调用 child.disconnect() 或子进程调用 process.disconnect() 时触发。

error:子进程无法创建、或无法被杀掉、或发消息给子进程失败时触发。

message:子进程通过 process.send() 发送消息时触发。

spawn:子进程创建成功时触发(Node.js v15.1版本才添加此事件)。

execexecFile 方法还额外提供了一个回调函数,会在子进程终止的时候触发。接下来进行详细分析:

exec

exec 方法用于执行 bash 命令,它的参数是一个命令字符串。例如统计当前目录下的文件数量,用 exec 函数的写法为:

const { exec } = require("child_process")
exec("find . -type f | wc -l", (err, stdout, stderr) => {
  if (err) return console.error(`exec error: ${err}`)
  console.log(`Number of files ${stdout}`)
})

exec 会新建一个子进程,然后缓存它的运行结果,运行结束后调用回调函数。

可能你已经想到了,exec 命令是比较危险的,假如把用户提供的字符串作为 exec 函数的参数,会面临命令行注入的风险,例如:

find . -type f | wc -l; rm -rf /;

另外,由于 exec 会在内存中缓存全部的输出结果,当数据比较大的时候,spawn 会是更好的选择。

execFile

execFile 和 exec 的区别在于它并不会创建 shell,而是直接执行命令,所以会更高效一点,例如:

const { execFile } = require("child_process")
const child = execFile("node", ["--version"], (error, stdout, stderr) => {
  if (error) throw error
  console.log(stdout)
})

由于没有创建 shell,程序的参数作为数组传入,因此具有较高的安全性。

spawn

spawn 函数和  execFile 类似,默认不开启 shell,但区别在于 execFile 会缓存命令行的输出,然后把结果传入回调函数中,而 spawn 则是以流的方式输出,有了流,就能非常方便的对接输入和输出了,例如典型的 wc 命令:

const child = spawn("wc")
process.stdin.pipe(child.stdin)
child.stdout.on("data", data => {
  console.log(`child stdout:\n${data}`)
})

此时就会从命令行 stdin 获取输入,当用户触发回车 + ctrl D 时就开始执行命令,并把结果从 stdout 输出。

wc 是 Word Count 的缩写,用于统计单词数,语法为:

wc [OPTION]... [FILE]...

如果在终端上输入 wc 命令并回车,这时候统计的是从键盘输入终端中的字符,再次按回车键,然后按 Ctrl + D 会输出统计的结果。

通过管道还可以组合复杂的命令,例如统计当前目录下的文件数量,在 linux 命令行中会这么写:

find . -type f | wc -l

在 Node.js 中的写法和命令行一模一样:

const find = spawn("find", [".", "-type", "f"])
const wc = spawn("wc", ["-l"])
find.stdout.pipe(wc.stdin)
wc.stdout.on("data", (data) => {
  console.log(`Number of files ${data}`)
})

spawn 有丰富的自定义配置,例如:

const child = spawn("find . -type f | wc -l", {
  stdio: "inherit", // 继承父进程的输入输出流
  shell: true, // 开启命令行模式
  cwd: "/Users/keliq/code", // 指定执行目录
  env: { ANSWER: 42 }, // 指定环境变量(默认是 process.env)
  detached: true, // 作为独立进程存在
})

fork

fork 函数是 spawn 函数的变体,使用 fork 创建的子进程和父进程之间会自动创建一个通信通道,子进程的全局对象 process 上面会挂载 send 方法。例如父进程 parent.js 代码:

const { fork } = require("child_process")
const forked = fork("./child.js")

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

forked.send({ hello: "world" })

子进程 child.js 代码:

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

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

当调用 fork("child.js")的时候,实际上就是用 node 来执行该文件中的代码,相当于 spawn('node', ['./child.js'])

fork 的一个典型的应用场景如下:假如现在用 Node.js 创建一个 Http 服务,当路由为 compute 的时候,执行一个耗时的运算。

const http = require("http")
const server = http.createServer()
server.on("request", (req, res) => {
  if (req.url === "/compute") {
    const sum = lonGComputation()
    return res.end(Sum is ${sum})
  } else {
    res.end("OK")
  }
})

server.listen(3000);

可以用下面的代码来模拟该耗时的运算:

const longComputation = () => {
  let sum = 0;
  for (let i = 0; i < 1e9; i++) {
    sum += i
  }
  return sum
}

那么在上线后,只要服务端收到了 compute 请求,由于 Node.js 是单线程的,耗时运算占用了 CPU,用户的其他请求都会阻塞在这里,表现出来的现象就是服务器无响应。

解决这个问题最简单的方法就是把耗时运算放到子进程中去处理,例如创建一个 compute.js 的文件,代码如下:

const longComputation = () => {
  let sum = 0;
  for (let i = 0; i < 1e9; i++) {
    sum += i;
  }
  return sum
}

process.on("message", msg => {
  const sum = longComputation()
  process.send(sum)
})

再把服务端的代码稍作改造:

const http = require("http")
const { fork } = require("child_process")
const server = http.createServer()
server.on("request", (req, res) => {
  if (req.url === "/compute") {
    const compute = fork("compute.js")
    compute.send("start")
    compute.on("message", sum => {
      res.end(Sum is ${sum})
    })
  } else {
    res.end("OK")
  }
})
server.listen(3000)

这样的话,主线程就不会阻塞,而是继续处理其他的请求,当耗时运算的结果返回后,再做出响应。其实更简单的处理方式是利用 cluster 模块,限于篇幅原因,后面再展开讲。

总结

掌握了上面四种创建子进程的方法之后,总结了以下三条规律:

  • 创建 node 子进程用 fork,因为自带通道方便通信。

  • 创建非 node 子进程用 execFile 或 spawn。如果输出内容较少用 execFile,会缓存结果并传给回调方便处理;如果输出内容多用 spawn,使用流的方式不会占用大量内存。

  • 执行复杂的、固定的终端命令用 exec,写起来更方便。但一定要记住 exec 会创建 shell,效率不如 execFile 和 spawn,且存在命令行注入的风险。

感谢各位的阅读,以上就是“Node.js中创建子进程的方法有哪些”的内容了,经过本文的学习后,相信大家对Node.js中创建子进程的方法有哪些这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是编程网,小编将为大家推送更多相关知识点的文章,欢迎关注!

--结束END--

本文标题: Node.js中创建子进程的方法有哪些

本文链接: https://www.lsjlt.com/news/83015.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Node.js中创建子进程的方法有哪些
    这篇文章主要讲解了“Node.js中创建子进程的方法有哪些”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Node.js中创建子进程的方法有哪些”吧!众所周知...
    99+
    2024-04-02
  • linux中创建子进程的方式有哪些
    在Linux中,有以下几种方式可以创建子进程:1. 使用fork()系统调用:fork()系统调用会创建一个与父进程完全相同的子进程...
    99+
    2023-09-11
    linux
  • Node.js中子进程与应用场景有哪些
    这篇文章主要介绍了Node.js中子进程与应用场景有哪些,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。背景由于ons基于 C艹 封装而来,不...
    99+
    2024-04-02
  • mfc创建线程的方法有哪些
    MFC (Microsoft Foundation Class) 是一个用于开发Windows应用程序的C++类库。在MFC中,可以...
    99+
    2023-09-18
    mfc
  • java创建线程的方法有哪些
    java中创建线程的方法有:1.使用Runnable接口创建;2.使用Thread继承类创建;3.使用Callable和Future创建;java中创建线程的方法有以下几种使用Runnable接口创建public class Runnabl...
    99+
    2024-04-02
  • MySQL中创建表的方法有哪些
    在MySQL中创建表的方法有以下几种: 使用CREATE TABLE语句:利用CREATE TABLE语句可以直接在MySQL中创...
    99+
    2024-04-09
    MySQL
  • JS中有哪些创建类的方法
    小编给大家分享一下JS中有哪些创建类的方法,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!具体如下:Javascript是一种基于...
    99+
    2024-04-02
  • 创建dblink的方法有哪些
    这篇文章主要介绍“创建dblink的方法有哪些”,在日常操作中,相信很多人在创建dblink的方法有哪些问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”创建dblink的方法有...
    99+
    2024-04-02
  • Java都有哪些创建线程的方法
    目录1.继承Thread类1.1 普通类继承Thread1.2 匿名内部类1.3 缺点分析2.实现Runnable接口2.1 普通类实现Runnable2.2 匿名Runnable实...
    99+
    2024-04-02
  • java多线程创建的方法有哪些
    在Java中,有以下几种方式可以创建多线程:1. 继承Thread类:创建一个新的类继承Thread类,并重写run()方法来定义线...
    99+
    2023-09-23
    java
  • Java创建多线程的方法有哪些
    这篇“Java创建多线程的方法有哪些”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Java创建多线程的方法有哪些”文章吧。J...
    99+
    2023-06-29
  • 创建session的方法有哪些
    创建session的方法有以下几种:1. 通过服务器端创建session:服务器端在收到客户端的请求后生成一个唯一的session ...
    99+
    2023-08-08
    session
  • linux创建进程的命令有哪些
    这篇“linux创建进程的命令有哪些”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“linu...
    99+
    2023-03-13
    linux
  • python的多线程创建的方法有哪些
    本篇内容介绍了“python的多线程创建的方法有哪些”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!python多线程一、线程的概念线程是CP...
    99+
    2023-07-04
  • Linux中有哪些创建文件的方法
    本篇文章为大家展示了Linux中有哪些创建文件的方法,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。在 Linux 上使用重定向符(>)创建一个文件标准重定向符允许我们创建一个 0KB 的空文件...
    99+
    2023-06-16
  • Python中列表的创建方法有哪些
    Python中列表的创建方法有以下几种:1. 使用方括号 [] 来创建一个空列表:pythonmy_list = []2. 使用方括...
    99+
    2023-10-20
    Python
  • mongodb创建表的方法有哪些
    在MongoDB中,不同于传统关系型数据库,MongoDB使用集合(Collection)来存储数据,而不是表。因此,并不需要像关系...
    99+
    2024-04-10
    mongodb
  • Java中创建String 对象的方法有哪些
    这篇文章将为大家详细讲解有关Java中创建String 对象的方法有哪些,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。创建 String 对象有三种方法String s1="我是字...
    99+
    2023-05-31
    java string ava
  • 在C#中创建单例的方法有哪些
    这期内容当中小编将会给大家带来有关在C#中创建单例的方法有哪些,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。第一种常见的方式创建单例: /// <summary> ...
    99+
    2023-06-09
  • java中线程池创建的方式有哪些
    本篇文章为大家展示了java中线程池创建的方式有哪些,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。Java可以用来干什么Java主要应用于:1. web开发;2. Android开发;3. 客户端开...
    99+
    2023-06-14
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作