nodejs篇 process模块

目录

前言

监听回调 beforeExit 、exit、uncaughtException

beforeExit 

exit

uncaughtException

Process常用属性

stdout

stdin

process方法

process.cwd(),process.chdir()

process.nextTick()

process.exit()

process.kill()


前言

process是nodejs提供的进程管理工具,nodejs其中一大特点,单进程,单线程。

既然如此,如何处理异步函数?node.js提供的API中有大量的回调函数,用于解决异步逻辑。所有的异步回调函数都继承了 events模块中EventEmitter这个类,而这个类实现的方式,都遵循着一项运行机制 eventLoop(事件循环)。

eventLoop实现的底层逻辑,有一部分就依赖于对进程的控制。

process模块可以直接从global获取,因为它们完全相等

const process = require("node:process");
console.log(process === global.process) // true

 nodejs其它相关内容学习

1. nodejs commonjs介绍

2. nodejs fs模块介绍

3. nodejs path模块介绍

4.nodejs events模块介绍

5.nodejs http模块介绍

6.nodejs net模块介绍

7.nodejs url模块介绍

监听回调 beforeExit 、exit、uncaughtException

const process = require("node:process");

// 当evnetLoop清空(既无宏任务也无微任务),在主进程关闭之前调用
process.on("beforeExit", (code) => {
  console.log("Process beforeExit event with code: ", code);
//   setTimeout(() => {
//     console.log(456);
//   }, 10);
    function a() {
        console.log('a')
    }
    a()
});

// 主进程彻底退出时调用,也可以理解为程序彻底结束时调用
process.on("exit", (code) => {
  console.log("Process exit event with code: ", code);
});

beforeExit 

调用的时机:每一次evnetLoop清空(既无宏任务也无微任务),在主进程关闭之前调用。

正常情况下,如果没有任何待处理的任务,Node进程会自动退出,设置beforeExit事件的监听函数以后,就可以提供一个机会,再部署一些任务,使得Node进程不退出。

注意点:

1. 如果是显式终止程序(比如调用process.exit()),或者因为发生未捕获的错误,而导致进程退出,这些场合不会触发beforeExit事件。(因为以上两种情况都不是evnetLoop被清空)

2. 当异步代码在回调中时,会再一次触发beforeExit ,可能会死循环,注意控制好异步代码的出口。

错误

const process = require("node:process");

process.on("beforeExit", (code) => {
  console.log("Process beforeExit event with code: ", code);
  setTimeout(() => {
    console.log(456);
  }, 10);
});

setTimeout会再一次为eventLoop添加一个宏任务,当eventLoop执行完宏任务,清空时,会再一次触发beforeExit,进入无限循环。。。

正确

const process = require("node:process");

var key = false;

// enventLoop已经清空之后调用,如果有新的异步开启,将再一次触发,进入死循环setTimeout,setImmediate等
process.on("beforeExit", (code) => {
  console.log("Process beforeExit event with code: ", code);
  if (key) {
    return;
  } else {
    setTimeout(() => {
      key = true;
    }, 10);
  }
});

exit

调用的时机:监听到进程即将关闭,在此之前执行的回调。

但回调同步执行完成之后,一定会将主进程关闭,停止程序的运行。

注意:1.与beforeExit不同,不能在回调中执行异步代码,因为回调同步执行完成后,就会立刻将主进程关闭,程序也会结束。

2. 显式终止程序(比如调用process.exit()),或者因为发生未捕获的错误,而导致进程退出,这些都会触发exit,算是弥补了beforeExit的不足。

uncaughtException

const process = require("node:process");

// 监听进程执行过程中的所有报错
process.on("uncaughtException", (err) => {
  console.error(
    "An unhandled exception is raised. Look at stack for more details"
  );
  console.error(err.stack);
  process.exit(1);
});

console.log(abc)
An unhandled exception is raised. Look at stack for more details
ReferenceError: abc is not defined
    at Object.<anonymous> (D:\Codes\Test\process.js:31:13)
    at Module._compile (internal/modules/cjs/loader.js:1085:14)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1114:10)
    at Module.load (internal/modules/cjs/loader.js:950:32)
    at Function.Module._load (internal/modules/cjs/loader.js:790:12)
    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:76:12)
    at internal/main/run_main_module.js:17:47

调用时机:监听Node的一个全局性事件uncaughtException,只要有错误没有捕获,就会触发这个事件。

Process常用属性

  • process.argv:返回一个数组,成员是当前进程的所有命令行参数。
  • process.env:返回一个对象,成员为当前Shell的环境变量,比如process.env.HOME
  • process.installPrefix:返回一个字符串,表示 Node 安装路径的前缀,比如/usr/local。相应地,Node 的执行文件目录为/usr/local/bin/node
  • process.pid:返回一个数字,表示当前进程的进程号。
  • process.platform:返回一个字符串,表示当前的操作系统,比如Linux
  • process.title:返回一个字符串,默认值为node,可以自定义该值。
  • process.version:返回一个字符串,表示当前使用的 Node 版本,比如v7.10.0

stdout

相当于console.log()

process.stdout.write(123 + '\n')
// 等价于
console.log(123 + '\n')

将文件读取出来,压缩并打印

var fs = require('fs');
var zlib = require('zlib');

fs.createReadStream('url.js')
  .pipe(zlib.createGzip())
  .pipe(process.stdout);

stdin

process.stdin返回一个对象,表示标准输入。感觉用处不大

process.stdin.pipe(process.stdout)

process方法

  • process.chdir():切换工作目录到指定目录。
  • process.cwd():返回运行当前脚本的工作目录的路径。
  • process.exit():退出当前进程。
  • process.getgid():返回当前进程的组ID(数值)。
  • process.getuid():返回当前进程的用户ID(数值)。
  • process.nextTick():指定回调函数在当前执行栈的尾部、下一次Event Loop之前执行。
  • process.on():监听事件。
  • process.setgid():指定当前进程的组,可以使用数字ID,也可以使用字符串ID。
  • process.setuid():指定当前进程的用户,可以使用数字ID,也可以使用字符串ID。

process.cwd(),process.chdir()

cwd方法返回进程的当前目录(绝对路径),chdir方法用来切换目录。

console.log(process.cwd(), process.chdir("../"));
console.log(process.cwd());

/** 
D:\Codes\Test undefined
D:\Codes
*/

注意process.cwd()__dirname的区别。前者进程发起时的位置,后者是脚本的位置,两者可能是不一致的。比如,node ./code/program.js,对于process.cwd()来说,返回的是当前目录.;对于__dirname来说,返回是脚本所在目录,即./code/program.js

process.nextTick()

将任务放到当前一轮事件循环(Event Loop)的尾部,当eventLoop下一个轮询到来前执行。其实这种设计模式很常见,vue中也有this.$nextTick,而在react中,其实也有类似的存在 import { nextTick } from 'react';

process.nextTick(function () {
  console.log('下一次Event Loop即将开始!');
});

setTimeout(function () {
  console.log("已经到了下一轮Event Loop!");
}, 0);

/** 
下一次Event Loop即将开始!
已经到了下一轮Event Loop!
*/

setTimeout(f,0)是将任务放到下一轮事件循环的头部,因此nextTick会比它先执行。另外,nextTick的效率更高,因为不用检查是否到了指定时间。

process.exit()

process.exit方法用来退出当前进程。它可以接受一个数值参数,如果参数大于0,表示程序出错,强制退出;如果等于0表示程序结束,正常退出,exit默认的参数是0。

try {
  // ....
  process.exit();
} catch (error) {
  if (error) {
    process.exit(1);
  }
}

这个函数会触发 exit监听回调f的执行  process.on("exit",f)

process.kill()

process.kill方法用来对指定ID的线程发送信号,默认为SIGINT信号,并且会结束对应的Id的线程。

process.kill(process.pid, 'SIGTERM');

process.exit([code]) 对于快速结束进程很有用。但在其他情况下,您可能希望在关闭之前向该进程传递一个信号以进行清理/正常关闭

Node.js 为 SIGINTSIGTERM 建立信号处理程序,Node.js 进程不会因收到这些信号而立即终止。相反,Node.js 将执行一系列清理操作,然后重新发出已处理的信号。

其实相对来说,用得比较少。

猜你喜欢

转载自blog.csdn.net/glorydx/article/details/128936029
今日推荐