一篇搞懂Node.js中的process

1,195 阅读3分钟

每一个Node应用都是运行在一个单独进程(process)中,而进程是线程容器。每一个process中可以运行Node提供的异步I/O的API,已提供了控制进程的API。例如:相信大家如果配置过vue/angular/react项目,这些项目中都是可以直接通过指定npm run build时的model读取根目录中对应的.env文件,而同时呢,咱们可以在一些基础文件中通过process.env就读到对应的model,对应不同的环境添加不同的设置。

什么是process

process 是Node中的线程容器,每一个Node应用会有一个process,开发者可以通过process对象控制和获取当前Node的进程。

Note 每一个npm run start起的项目都是一个Node应用,都会拥有一个process对象。

process中的Evnet

process的Event其实是Node中的EventEmitter的一个实例化对象, Node中的EventEmitter,Node的event基本都遵循EventEmitter格式。

beforeExit 事件

当Node执行完(清空)event loop并且没有其他事件安排时被触发。通常当Node进程在没有事件安排时会退出,但是如果注册了一个beforExit事件监听者可以进行异步回调,能使得Node的进程继续。

Node会给beforExit的回调函数传递process.exitCode的值,作为唯一参数。 如果是通过process.exit()事件或者因为未捕获的异常触发的显示终止,beforExit事件不会被触发。 基于以上的原因,process.beforExit事件不应该是process.exit事件的替代者。

  const process require 'node:process'; 
  // 在Node环境中运行可以将'node:process'改为'process'
  // 在npm管理的项目中,可以不引用process,直接使用process对象

  process.on('beforeExit', (code) => {
    console.log('Process beforeExit event with code: ', code);
  });

  process.on('exit', (code) => {
    console.log('Process exit event with code: ', code);
  });

  console.log('This message is displayed first.');

disconnect 事件

如果Node的process是通过IPC渠道(Child Process or Cluster)产生的,在IPC渠道被关闭时会触发disconnect事件

exit 事件

有两种情况会触发exit事件,如下:

  • 当显示调用process.exit()
  • 当Node的evnet loop没有任务安排了

exit事件中不能阻止evnet loop退出,一旦所有的exit回调全部执行完,对应的Node process也会终止。 使用process.exitCode属性指定的exit code调用exit的回调方法,或者将exitCode作为参数传递给process.exit()方法

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

  process.on('exit', (code) => {
    console.log(`About to exit with code: ${code}`);
  });

exit的回调方法必须是同步方法。Node的进程在exit事件执行后立即退出,从而导致了任何人在evnet loop中排队的额外工作被放弃。

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

process.on('exit', (code) => {
  //这个setTimeout永远不会被执行
  setTimeout(() => {
    console.log('This will not run');
  }, 0);
});

process.argv

process的argv属性是一个在当前进程中,在命令行中输入的命令的数组,当开发cli或者运用cli时,执行的命令行代码,将会把输入的命令通过process.argv属性传给node,供Node调用执行。

//在npm项目中,执行`npm run start`命令
//process.argv会受到形如如下的格式
0: /usr/nodejs/node
1: /usr/nodejs/node_modules/npm/core/index.js
2: run
3: start

process.env

该属性返回一个包含用户环境的对象,形如environ 例如:

  {
    TERM: 'xterm-256color',
    SHELL: '/usr/local/bin/bash',
    USER: 'maciej',
    PATH: '~/.bin/:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin',
    PWD: '/Users/maciej',
    EDITOR: 'vim',
    SHLVL: '1',
    HOME: '/Users/maciej',
    LOGNAME: 'maciej',
    _: '/usr/local/bin/node'
  }

也可以在env对象中定义自定义属性,例如:

const { env } = require('node:process');

env.foo = 'bar';
console.log(env.foo);

process.exit([code])

Node中的显示退出方法,可以通过传指定的code,指定调用exit code为code的退出方法,如果不传,exit方法用任一成功的code '0'或者被指定的process.exitCode。Node在exit事件回调函数被调用前不会退出。


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

exit(1);

// This is an example of what *not* to do:
if (someConditionNotMet()) {
  printUsageToStdout();
  exit(1);
}

// How to properly set the exit code while letting
// the process exit gracefully.
if (someConditionNotMet()) {
  printUsageToStdout();
  process.exitCode = 1;
}

以上是常用的一些方法,如果感兴趣,可以参考Node官网