An article to talk about processes and sub-processes in Node.js
This article will give you an in-depth understanding of the processes and sub-processes in Node. I hope it will be helpful to everyone!
Process: process module
The process module is a tool provided by nodejs for developers to interact with the current process. Provides many practical APIs. [Related tutorial recommendations: nodejs video tutorial]
Start from the document, get a glimpse of the leopard, and further understand and learn the process module:
- How to process command parameters?
- How to deal with the working directory?
- How to handle exceptions?
- How to handle process exit?
- The standard stream object of process
- In-depth understanding of process.nextTick
How to handle command parameters?
Command line parameters refer to two aspects:
- The parameters passed to node. For example,
node --harmony script.js --version
,--harmony
is the parameter passed to node - The parameter passed to the process. For example, in
node script.js --version --help
,--version --help
is the parameter passed to the process
They pass# respectively ##process.argv and
process.execArgv to obtain.
How to deal with the working directory?
The current working directory can be obtained throughprocess.cwd().
process.chdir(directory), and an exception will be thrown if it fails. The practice is as follows:
function safeChdir(dir) { try { process.chdir(dir); return true; } catch (error) { return false; } }
How to handle exceptions?
uncaughtException event
Nodejs can catch exceptions through try-catch. If the exception is not caught, it will always bubble up from the bottom to the event loop. If the exception that bubbles up to the event loop is not handled, it will cause the current process to exit abnormally. According to the documentation, you can handle uncaught exceptions by listening to the uncaughtException event of the process:process.on("uncaughtException", (err, origin) => { console.log(err.message); }); const a = 1 / b; console.log("abc"); // 不会执行In the above code, the output of the console is:
b is not defined. The error message was caught and the process exited with
0. Developers can clear some allocated resources (file descriptors, handles, etc.) in the uncaughtException event, and restarting the process is not recommended.
unhandledRejection event
If a Promise callback exception is not caught by.catch(), then the unhandledRejection event of the process will be triggered:
process.on("unhandledRejection", (err, promise) => { console.log(err.message); }); Promise.reject(new Error("错误信息")); // 未被catch捕获的异常,交由unhandledRejection事件处理
warning Event
Warnings are not a formal part of the Node.js and Javascript error handling process. Node.js can issue alerts once it detects coding practices that may lead to application performance issues, defects, or security risks. For example, in the previous code, if an uncaught promise callback exception occurs, the warning event will be triggered. Refer to the nodejs advanced video explanation:How to handle process exit?
process.exit() vs process.exitCode
A nodejs process can specify the exit code through process.exit(), directly quit.It is not recommended to use process.exit() directly, which will cause the tasks in the event loop to not be processed directly, and may lead to truncation and loss of data (such as the writing of stdout).
setTimeout(() => { console.log("我不会执行"); }); process.exit(0);
The correct and safe handling is to , set process.exitCode, and allow the process to exit naturally.
setTimeout(() => { console.log("我不会执行"); }); process.exitCode = 1;
beforeExit event
The events used to handle process exit are: beforeExit event and exit event. The beforeExit event is fired when Node.js clears its event loop and has no more work to schedule. For example, if you need some asynchronous operations before exiting, you can write it in the beforeExit event:let hasSend = false; process.on("beforeExit", () => { if (hasSend) return; // 避免死循环 setTimeout(() => { console.log("mock send data to serve"); hasSend = true; }, 500); }); console.log("......."); // 输出: // ....... // mock send data to serveNote: If it is an asynchronous task in the beforeExit event, it will be added to the task queue. At this time, after the task queue completes all tasks, the beforeExit event is triggered again. Therefore, if it is not handled,
an infinite loop may occur. If exit() is called explicitly, this event will not be triggered.
exit event
In the exit event, only synchronous operations can be performed. After calling the 'exit' event listener, the Node.js process will exit immediately, causing any other work still queued in the event loop to be abandoned.Standard stream object of process
process 提供了 3 个标准流。需要注意的是,它们有些在某些时候是同步阻塞的(请见文档)。
- process.stderr:WriteStream 类型,
console.error
的底层实现,默认对应屏幕 - process.stdout:WriteStream 类型,
console.log
的底层实现,默认对应屏幕 - process.stdin:ReadStream 类型,默认对应键盘输入
下面是基于“生产者-消费者模型”的读取控制台输入并且及时输出的代码:
process.stdin.setEncoding("utf8"); process.stdin.on("readable", () => { let chunk; while ((chunk = process.stdin.read()) !== null) { process.stdout.write(`>>> ${chunk}`); } }); process.stdin.on("end", () => { process.stdout.write("结束"); });
关于事件的含义,还是请看stream 的文档。
深入理解 process.nextTick
我第一次看到 process.nextTick 的时候是比较懵的,看文档可以知道,它的用途是:把回调函数作为微任务,放入事件循环的任务队列中。但这么做的意义是什么呢?
因为 nodejs 并不适合计算密集型的应用,一个进程就一个线程,在当下时间点上,就一个事件在执行。那么,如果我们的事件占用了很多 cpu 时间,那么之后的事件就要等待非常久。所以,nodejs 的一个编程原则是尽量缩短每一个事件的执行事件。process.nextTick 的作用就在这,将一个大的任务分解成多个小的任务。示例代码如下:
// 被拆分成2个函数执行 function BigThing() { doPartThing(); process.nextTick(() => finishThing()); }
在事件循环中,何时执行 nextTick 注册的任务呢?请看下面的代码:
setTimeout(function() { console.log("第一个1秒"); process.nextTick(function() { console.log("第一个1秒:nextTick"); }); }, 1000); setTimeout(function() { console.log("第2个1秒"); }, 1000); console.log("我要输出1"); process.nextTick(function() { console.log("nextTick"); }); console.log("我要输出2");
输出的结果如下,nextTick 是早于 setTimeout:
我要输出1 我要输出2 nextTick 第一个1秒 第一个1秒:nextTick 第2个1秒
在浏览器端,nextTick 会退化成 setTimeout(callback, 0)
。但在 nodejs 中请使用 nextTick 而不是 setTimeout,前者效率更高,并且严格来说,两者创建的事件在任务队列中顺序并不一样(请看前面的代码)。
子进程:child_process模块
掌握 nodejs 的 child_process 模块能够极大提高 nodejs 的开发能力,例如主从进程来优化 CPU 计算的问题,多进程开发等等。本文从以下几个方面介绍 child_process 模块的使用:
- 创建子进程
- 父子进程通信
- 独立子进程
- 进程管道
创建子进程
nodejs 的 child_process 模块创建子进程的方法:spawn, fork, exec, execFile。它们的关系如下:
- fork, exec, execFile 都是通过 spawn 来实现的。
- exec 默认会创建 shell。execFile 默认不会创建 shell,意味着不能使用 I/O 重定向、file glob,但效率更高。
- spawn、exec、execFile 都有同步版本,可能会造成进程阻塞。
child_process.spawn()
的使用:
const { spawn } = require("child_process"); // 返回ChildProcess对象,默认情况下其上的stdio不为null const ls = spawn("ls", ["-lh"]); ls.stdout.on("data", data => { console.log(`stdout: ${data}`); }); ls.stderr.on("data", data => { console.error(`stderr: ${data}`); }); ls.on("close", code => { console.log(`子进程退出,退出码 ${code}`); });
child_process.exec()
的使用:
const { exec } = require("child_process"); // 通过回调函数来操作stdio exec("ls -lh", (err, stdout, stderr) => { if (err) { console.error(`执行的错误: ${err}`); return; } console.log(`stdout: ${stdout}`); console.error(`stderr: ${stderr}`); });
父子进程通信
fork()
返回的 ChildProcess 对象,监听其上的 message 事件,来接受子进程消息;调用 send 方法,来实现 IPC。
parent.js 代码如下:
const { fork } = require("child_process"); const cp = fork("./sub.js"); cp.on("message", msg => { console.log("父进程收到消息:", msg); }); cp.send("我是父进程");
sub.js 代码如下:
process.on("message", m => { console.log("子进程收到消息:", m); }); process.send("我是子进程");
运行后结果:
父进程收到消息: 我是子进程 子进程收到消息: 我是父进程
独立子进程
在正常情况下,父进程一定会等待子进程退出后,才退出。如果想让父进程先退出,不受到子进程的影响,那么应该:
- 调用 ChildProcess 对象上的
unref()
-
options.detached
设置为 true - 子进程的 stdio 不能是连接到父进程
main.js 代码如下:
const { spawn } = require("child_process"); const subprocess = spawn(process.argv0, ["sub.js"], { detached: true, stdio: "ignore" }); subprocess.unref();
sub.js 代码如下:
setInterval(() => {}, 1000);
进程管道
options.stdio 选项用于配置在父进程和子进程之间建立的管道。 默认情况下,子进程的 stdin、 stdout 和 stderr 会被重定向到 ChildProcess 对象上相应的 subprocess.stdin、subprocess.stdout 和 subprocess.stderr 流。 这意味着可以通过监听其上的 data
事件,在父进程中获取子进程的 I/O 。
可以用来实现“重定向”:
const fs = require("fs"); const child_process = require("child_process"); const subprocess = child_process.spawn("ls", { stdio: [ 0, // 使用父进程的 stdin 用于子进程。 "pipe", // 把子进程的 stdout 通过管道传到父进程 。 fs.openSync("err.out", "w") // 把子进程的 stderr 定向到一个文件。 ] });
也可以用来实现"管道运算符":
const { spawn } = require("child_process"); const ps = spawn("ps", ["ax"]); const grep = spawn("grep", ["ssh"]); ps.stdout.on("data", data => { grep.stdin.write(data); }); ps.stderr.on("data", err => { console.error(`ps stderr: ${err}`); }); ps.on("close", code => { if (code !== 0) { console.log(`ps 进程退出,退出码 ${code}`); } grep.stdin.end(); }); grep.stdout.on("data", data => { console.log(data.toString()); }); grep.stderr.on("data", data => { console.error(`grep stderr: ${data}`); }); grep.on("close", code => { if (code !== 0) { console.log(`grep 进程退出,退出码 ${code}`); } });
更多node相关知识,请访问:nodejs 教程!
The above is the detailed content of An article to talk about processes and sub-processes in Node.js. For more information, please follow other related articles on the PHP Chinese website!

JavaScript is widely used in websites, mobile applications, desktop applications and server-side programming. 1) In website development, JavaScript operates DOM together with HTML and CSS to achieve dynamic effects and supports frameworks such as jQuery and React. 2) Through ReactNative and Ionic, JavaScript is used to develop cross-platform mobile applications. 3) The Electron framework enables JavaScript to build desktop applications. 4) Node.js allows JavaScript to run on the server side and supports high concurrent requests.

Python is more suitable for data science and automation, while JavaScript is more suitable for front-end and full-stack development. 1. Python performs well in data science and machine learning, using libraries such as NumPy and Pandas for data processing and modeling. 2. Python is concise and efficient in automation and scripting. 3. JavaScript is indispensable in front-end development and is used to build dynamic web pages and single-page applications. 4. JavaScript plays a role in back-end development through Node.js and supports full-stack development.

C and C play a vital role in the JavaScript engine, mainly used to implement interpreters and JIT compilers. 1) C is used to parse JavaScript source code and generate an abstract syntax tree. 2) C is responsible for generating and executing bytecode. 3) C implements the JIT compiler, optimizes and compiles hot-spot code at runtime, and significantly improves the execution efficiency of JavaScript.

JavaScript's application in the real world includes front-end and back-end development. 1) Display front-end applications by building a TODO list application, involving DOM operations and event processing. 2) Build RESTfulAPI through Node.js and Express to demonstrate back-end applications.

The main uses of JavaScript in web development include client interaction, form verification and asynchronous communication. 1) Dynamic content update and user interaction through DOM operations; 2) Client verification is carried out before the user submits data to improve the user experience; 3) Refreshless communication with the server is achieved through AJAX technology.

Understanding how JavaScript engine works internally is important to developers because it helps write more efficient code and understand performance bottlenecks and optimization strategies. 1) The engine's workflow includes three stages: parsing, compiling and execution; 2) During the execution process, the engine will perform dynamic optimization, such as inline cache and hidden classes; 3) Best practices include avoiding global variables, optimizing loops, using const and lets, and avoiding excessive use of closures.

Python is more suitable for beginners, with a smooth learning curve and concise syntax; JavaScript is suitable for front-end development, with a steep learning curve and flexible syntax. 1. Python syntax is intuitive and suitable for data science and back-end development. 2. JavaScript is flexible and widely used in front-end and server-side programming.

Python and JavaScript have their own advantages and disadvantages in terms of community, libraries and resources. 1) The Python community is friendly and suitable for beginners, but the front-end development resources are not as rich as JavaScript. 2) Python is powerful in data science and machine learning libraries, while JavaScript is better in front-end development libraries and frameworks. 3) Both have rich learning resources, but Python is suitable for starting with official documents, while JavaScript is better with MDNWebDocs. The choice should be based on project needs and personal interests.


Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Atom editor mac version download
The most popular open source editor

SublimeText3 Linux new version
SublimeText3 Linux latest version

mPDF
mPDF is a PHP library that can generate PDF files from UTF-8 encoded HTML. The original author, Ian Back, wrote mPDF to output PDF files "on the fly" from his website and handle different languages. It is slower than original scripts like HTML2FPDF and produces larger files when using Unicode fonts, but supports CSS styles etc. and has a lot of enhancements. Supports almost all languages, including RTL (Arabic and Hebrew) and CJK (Chinese, Japanese and Korean). Supports nested block-level elements (such as P, DIV),

Zend Studio 13.0.1
Powerful PHP integrated development environment

SecLists
SecLists is the ultimate security tester's companion. It is a collection of various types of lists that are frequently used during security assessments, all in one place. SecLists helps make security testing more efficient and productive by conveniently providing all the lists a security tester might need. List types include usernames, passwords, URLs, fuzzing payloads, sensitive data patterns, web shells, and more. The tester can simply pull this repository onto a new test machine and he will have access to every type of list he needs.