源代码: lib/process.js
process
对象提供有关当前 Node.js 进程的信息并对其进行控制。
虽然它作为全局可用,但是建议通过 require 或 import 显式地访问它:
import process from 'process';
const process = require('process');
process
对象是 EventEmitter
的实例。
'beforeExit'
事件#当 Node.js 清空其事件循环并且没有额外的工作要安排时,则会触发 'beforeExit'
事件。
通常情况下,当没有工作要调度时,Node.js 进程会退出,但是注册在 'beforeExit'
事件上的监听器可以进行异步的调用,从而使 Node.js 进程继续。
调用监听器回调函数时将 process.exitCode
的值作为唯一的参数传入。
对于导致显式终止的条件,例如调用 process.exit()
或未捕获的异常,则不会触发 'beforeExit'
事件。
'beforeExit'
不应用作 'exit'
事件的替代,除非打算安排额外的工作。
import process from '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.');
// 打印:
// This message is displayed first.
// Process beforeExit event with code: 0
// Process exit event with code: 0
const process = require('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.');
// 打印:
// This message is displayed first.
// Process beforeExit event with code: 0
// Process exit event with code: 0
'disconnect'
事件#如果 Node.js 进程是使用 IPC 通道衍生(参见子进程和集群文档),则在 IPC 通道关闭时将触发 'disconnect'
事件。
'exit'
事件#code
<integer>当 Node.js 进程由于以下任一原因即将退出时,则会触发 'exit'
事件:
process.exit()
方法被显式调用;此时没有办法阻止事件循环的退出,一旦所有 'exit'
监听器都运行完毕,则 Node.js 进程将终止。
监听器回调函数使用 process.exitCode
属性指定的退出码或传给 process.exit()
方法的 exitCode
参数调用。
import process from 'process';
process.on('exit', (code) => {
console.log(`About to exit with code: ${code}`);
});
const process = require('process');
process.on('exit', (code) => {
console.log(`About to exit with code: ${code}`);
});
监听器函数必须只执行同步的操作。
Node.js 进程将在调用 'exit'
事件监听器之后立即退出,从而使任何仍在事件循环中排队的其他工作被丢弃。
例如,在以下示例中,超时永远不会发生:
import process from 'process';
process.on('exit', (code) => {
setTimeout(() => {
console.log('This will not run');
}, 0);
});
const process = require('process');
process.on('exit', (code) => {
setTimeout(() => {
console.log('This will not run');
}, 0);
});
'message'
事件#message
<Object> | <boolean> | <number> | <string> | <null> 解析的 JSON 对象或可序列化的原始值。sendHandle
<net.Server> | <net.Socket> net.Server
或 net.Socket
对象、或未定义。如果 Node.js 进程是使用 IPC 通道衍生(参见子进程和集群文档),则每当子进程收到父进程使用 childprocess.send()
发送的消息时,就会触发 'message'
事件。
消息经过序列化和解析。 结果消息可能与最初发送的消息不同。
如果在衍生进程时将 serialization
选项设置为 advanced
,则 message
参数可以包含 JSON 无法表示的数据。
有关更多详细信息,请参阅子进程的高级序列化。
'multipleResolves'
事件#type
<string> 解决类型
'resolve'
或 'reject'
之一。promise
<Promise> 不止一次解决或拒绝的 promise。value
<any> 在原始解决之后解决或拒绝 promise 的值。每当 Promise
满足以下任一条件时,就会触发 'multipleResolves'
事件:
这对于在使用 Promise
构造函数时跟踪应用程序中的潜在错误很有用,因为多个解决被静默吞下。
但是,此事件的发生并不一定表示错误。
例如,Promise.race()
可以触发 'multipleResolves'
事件。
import process from 'process';
process.on('multipleResolves', (type, promise, reason) => {
console.error(type, promise, reason);
setImmediate(() => process.exit(1));
});
async function main() {
try {
return await new Promise((resolve, reject) => {
resolve('First call');
resolve('Swallowed resolve');
reject(new Error('Swallowed reject'));
});
} catch {
throw new Error('Failed');
}
}
main().then(console.log);
// resolve: Promise { 'First call' } 'Swallowed resolve'
// reject: Promise { 'First call' } Error: Swallowed reject
// at Promise (*)
// at new Promise (<anonymous>)
// at main (*)
// First call
const process = require('process');
process.on('multipleResolves', (type, promise, reason) => {
console.error(type, promise, reason);
setImmediate(() => process.exit(1));
});
async function main() {
try {
return await new Promise((resolve, reject) => {
resolve('First call');
resolve('Swallowed resolve');
reject(new Error('Swallowed reject'));
});
} catch {
throw new Error('Failed');
}
}
main().then(console.log);
// resolve: Promise { 'First call' } 'Swallowed resolve'
// reject: Promise { 'First call' } Error: Swallowed reject
// at Promise (*)
// at new Promise (<anonymous>)
// at main (*)
// First call
'rejectionHandled'
事件#promise
<Promise> 最近处理的 promise。每当 Promise
被拒绝并且错误句柄被附加到它(例如使用 promise.catch()
)晚于一轮 Node.js 事件循环时,则 'rejectionHandled'
事件就会触发。
Promise
对象会在 'unhandledRejection'
事件中先处理,但在处理过程中获得了拒绝句柄。
对于 Promise
链,没有始终可以处理拒绝的顶层概念。
由于本质上是异步的,Promise
拒绝可以在未来的某个时间点处理,可能比触发 'unhandledRejection'
事件所需的事件循环轮询要晚得多。
另一种表述方式是,与同步代码中未处理的异常列表不断增长不同,promise 中未处理的拒绝列表可能会不断增长和缩小。
在同步代码中,当未处理的异常列表增长时,会触发 'uncaughtException'
事件。
在异步代码中,当未处理的拒绝列表增长时,会触发 'unhandledRejection'
事件,当未处理的拒绝列表缩小时,会触发 'rejectionHandled'
事件。
import process from 'process';
const unhandledRejections = new Map();
process.on('unhandledRejection', (reason, promise) => {
unhandledRejections.set(promise, reason);
});
process.on('rejectionHandled', (promise) => {
unhandledRejections.delete(promise);
});
const process = require('process');
const unhandledRejections = new Map();
process.on('unhandledRejection', (reason, promise) => {
unhandledRejections.set(promise, reason);
});
process.on('rejectionHandled', (promise) => {
unhandledRejections.delete(promise);
});
在这个例子中,unhandledRejections
Map
将随着时间的推移而增长和缩小,反映了开始未处理然后变成处理的拒绝。
可以定期在错误日志中记录此类错误(这可能最适合长时间运行的应用程序)或在进程退出时(这可能对脚本最方便)。
'uncaughtException'
事件#err
<Error> 未捕获的异常。origin
<string> 指示异常是源自未处理的拒绝还是源自同步错误。
可以是 'uncaughtException'
或 'unhandledRejection'
。
后者用于在基于 Promise
的异步上下文中发生异常(或者如果 Promise
被拒绝)并且 --unhandled-rejections
标志设置为 strict
或 throw
(这是默认值)并且拒绝未处理,或者发生拒绝时 在命令行入口点的 ES 模块静态加载阶段。当未捕获的 JavaScript 异常一直冒泡回到事件循环时,则会触发 'uncaughtException'
事件。
默认情况下,Node.js 通过将堆栈跟踪打印到 stderr
并以代码 1 退出,覆盖任何先前设置的 process.exitCode
来处理此类异常。
为 'uncaughtException'
事件添加句柄会覆盖此默认行为。
或者,更改 'uncaughtException'
处理程序中的 process.exitCode
,这将导致进程以提供的退出码退出。
否则,在存在此类句柄的情况下,进程将以 0 退出。
import process from 'process';
process.on('uncaughtException', (err, origin) => {
fs.writeSync(
process.stderr.fd,
`Caught exception: ${err}\n` +
`Exception origin: ${origin}`
);
});
setTimeout(() => {
console.log('This will still run.');
}, 500);
// 故意引发异常,但不捕获。
nonexistentFunc();
console.log('This will not run.');
const process = require('process');
process.on('uncaughtException', (err, origin) => {
fs.writeSync(
process.stderr.fd,
`Caught exception: ${err}\n` +
`Exception origin: ${origin}`
);
});
setTimeout(() => {
console.log('This will still run.');
}, 500);
// 故意引发异常,但不捕获。
nonexistentFunc();
console.log('This will not run.');
通过安装 'uncaughtExceptionMonitor'
监听器,可以在不覆盖退出进程的默认行为的情况下监视 'uncaughtException'
事件。
'uncaughtException'
是用于异常处理的粗略机制,仅用作最后的手段。
事件_不应该_用作 On Error Resume Next
的等价物。
未处理的异常本质上意味着应用程序处于未定义状态。
在没有从异常中正确恢复的情况下尝试恢复应用程序代码可能会导致其他不可预见和不可预测的问题。
从事件句柄中抛出的异常将不会被捕获。 而是,该进程将以非零退出码退出,并将打印堆栈跟踪。 这是为了避免无限递归。
尝试在未捕获异常后正常恢复类似于升级计算机时拔掉电源线。 十有八九,什么都没有发生。 但是第十次,系统损坏了。
'uncaughtException'
的正确用法是在关闭进程之前对分配的资源(例如文件描述符、句柄等)执行同步清理。
在 'uncaughtException'
之后恢复正常操作是不安全的。
为了以更可靠的方式重新启动崩溃的应用程序,无论 'uncaughtException'
是否触发,都应该在单独的进程中使用外部监视器来检测应用程序故障并根据需要恢复或重新启动。
'uncaughtExceptionMonitor'
事件#err
<Error> 未捕获的异常。origin
<string> 指示异常是源自未处理的拒绝还是源自同步错误。
可以是 'uncaughtException'
或 'unhandledRejection'
。
后者用于在基于 Promise
的异步上下文中发生异常(或者如果 Promise
被拒绝)并且 --unhandled-rejections
标志设置为 strict
或 throw
(这是默认值)并且拒绝未处理,或者发生拒绝时 在命令行入口点的 ES 模块静态加载阶段。'uncaughtExceptionMonitor'
事件在 'uncaughtException'
事件触发或通过 process.setUncaughtExceptionCaptureCallback()
安装的钩子被调用之前触发。
一旦触发 'uncaughtException'
事件,则安装 'uncaughtExceptionMonitor'
监听器不会更改行为。
如果没有安装 'uncaughtException'
监听器,则进程仍然会崩溃。
import process from 'process';
process.on('uncaughtExceptionMonitor', (err, origin) => {
MyMonitoringTool.logSync(err, origin);
});
// 故意引发异常,但不捕获。
nonexistentFunc();
// 仍然崩溃 Node.js
const process = require('process');
process.on('uncaughtExceptionMonitor', (err, origin) => {
MyMonitoringTool.logSync(err, origin);
});
// 故意引发异常,但不捕获。
nonexistentFunc();
// 仍然崩溃 Node.js
'unhandledRejection'
事件#每当 Promise
被拒绝并且在事件循环的一个轮询内没有错误句柄附加到承诺时,则会触发 'unhandledRejection'
事件。
使用 Promise 进行编程时,异常被封装为“被拒绝的 promise”。
拒绝可以使用 promise.catch()
捕获和处理,并通过 Promise
链传播。
'unhandledRejection'
事件对于检测和跟踪尚未处理的被拒绝的 promise 很有用。
import process from 'process';
process.on('unhandledRejection', (reason, promise) => {
console.log('Unhandled Rejection at:', promise, 'reason:', reason);
// 应用程序特定的日志记录,在此处抛出错误或其他逻辑
});
somePromise.then((res) => {
return reportToUser(JSON.pasre(res)); // 注意错别字 (`pasre`)
}); // 无 `.catch()` 或 `.then()`
const process = require('process');
process.on('unhandledRejection', (reason, promise) => {
console.log('Unhandled Rejection at:', promise, 'reason:', reason);
// 应用程序特定的日志记录,在此处抛出错误或其他逻辑
});
somePromise.then((res) => {
return reportToUser(JSON.pasre(res)); // 注意错别字 (`pasre`)
}); // 无 `.catch()` 或 `.then()`
以下也将触发 'unhandledRejection'
事件被触发:
import process from 'process';
function SomeResource() {
// 最初将加载状态设置为被拒绝的 promise
this.loaded = Promise.reject(new Error('Resource not yet loaded!'));
}
const resource = new SomeResource();
// resource.loaded 上没有 .catch 或 .then
const process = require('process');
function SomeResource() {
// 最初将加载状态设置为被拒绝的 promise
this.loaded = Promise.reject(new Error('Resource not yet loaded!'));
}
const resource = new SomeResource();
// resource.loaded 上没有 .catch 或 .then
在此示例情况下,可以将拒绝作为开发人员错误进行跟踪,这通常是其他 'unhandledRejection'
事件的情况。
为了解决此类故障,可以将非操作 .catch(() => { })
句柄附加到 resource.loaded
,这将阻止触发 'unhandledRejection'
事件。
'warning'
事件#warning
<Error> 警告的主要属性是:
每当 Node.js 触发进程警告时,则会触发 'warning'
事件。
进程警告类似于错误,因为其描述了引起用户注意的异常情况。 但是,警告不是正常 Node.js 和 JavaScript 错误处理流程的一部分。 Node.js 可以在检测到可能导致次优应用程序性能、错误或安全漏洞的不良编码实践时触发警告。
import process from 'process';
process.on('warning', (warning) => {
console.warn(warning.name); // 打印警告名称
console.warn(warning.message); // 打印警告信息
console.warn(warning.stack); // 打印堆栈跟踪
});
const process = require('process');
process.on('warning', (warning) => {
console.warn(warning.name); // 打印警告名称
console.warn(warning.message); // 打印警告信息
console.warn(warning.stack); // 打印堆栈跟踪
});
默认情况下,Node.js 会将进程警告打印到 stderr
。
--no-warnings
命令行选项可用于抑制默认控制台输出,但 'warning'
事件仍将由 process
对象触发。
以下示例说明了在向事件添加过多监听器时打印到 stderr
的警告:
$ node
> events.defaultMaxListeners = 1;
> process.on('foo', () => {});
> process.on('foo', () => {});
> (node:38638) MaxListenersExceededWarning: Possible EventEmitter memory leak
detected. 2 foo listeners added. Use emitter.setMaxListeners() to increase limit
相比之下,以下示例关闭默认警告输出并向 'warning'
事件添加自定义句柄:
$ node --no-warnings
> const p = process.on('warning', (warning) => console.warn('Do not do that!'));
> events.defaultMaxListeners = 1;
> process.on('foo', () => {});
> process.on('foo', () => {});
> Do not do that!
--trace-warnings
命令行选项可用于使警告的默认控制台输出包括警告的完整堆栈跟踪。
使用 --throw-deprecation
命令行标志启动 Node.js 将导致自定义弃用警告作为异常抛出。
使用 --trace-deprecation
命令行标志将导致自定义弃用与堆栈跟踪一起打印到 stderr
。
使用 --no-deprecation
命令行标志将抑制自定义弃用的所有报告。
*-deprecation
命令行标志仅影响使用名称 'DeprecationWarning'
的警告。
'worker'
事件#创建新的 <Worker> 线程后会触发 'worker'
事件。
请参阅 process.emitWarning()
方法以发出自定义或特定于应用程序的警告。
Node.js 触发的警告类型(由 name
属性标识)没有严格的指导方针。
可以随时添加新类型的警告。
一些最常见的警告类型包括:
'DeprecationWarning'
- 表示使用已弃用的 Node.js API 或功能。
此类警告必须包含标识弃用代码的 'code'
属性。'ExperimentalWarning'
- 表示使用实验的 Node.js API 或功能。
必须谨慎使用此类功能,因为它们可能随时更改,并且不受与受支持功能相同的严格语义版本控制和长期支持政策的约束。'MaxListenersExceededWarning'
- 表示在 EventEmitter
或 EventTarget
上注册了太多给定事件的监听器。
这通常表示内存泄漏。'TimeoutOverflowWarning'
- 表示已向 setTimeout()
或 setInterval()
函数提供了无法容纳在 32 位有符号整数内的数值。'UnsupportedWarning'
- 表示使用不受支持的选项或功能,这些选项或功能将被忽略而不是被视为错误。
一个示例是在使用 HTTP/2 兼容性 API 时使用 HTTP 响应状态消息。当 Node.js 进程收到信号时,则将触发信号事件。
有关标准 POSIX 信号名称(例如 'SIGINT'
、'SIGHUP'
等)的列表,请参阅 signal(7)
。
信号在 Worker
线程上不可用。
信号句柄将接收信号的名称('SIGINT'
、'SIGTERM'
等)作为第一个参数。
每个事件的名称将是信号的大写通用名称(例如 'SIGINT'
表示 SIGINT
信号)。
import process from 'process';
// 从标准输入开始读取,因此进程不会退出。
process.stdin.resume();
process.on('SIGINT', () => {
console.log('Received SIGINT. Press Control-D to exit.');
});
// 使用单个函数处理多个信号
function handle(signal) {
console.log(`Received ${signal}`);
}
process.on('SIGINT', handle);
process.on('SIGTERM', handle);
const process = require('process');
// 从标准输入开始读取,因此进程不会退出。
process.stdin.resume();
process.on('SIGINT', () => {
console.log('Received SIGINT. Press Control-D to exit.');
});
// 使用单个函数处理多个信号
function handle(signal) {
console.log(`Received ${signal}`);
}
process.on('SIGINT', handle);
process.on('SIGTERM', handle);
'SIGUSR1'
由 Node.js 预留以启动调试器。
可以安装监听器,但这样做可能会干扰调试器。'SIGTERM'
和 'SIGINT'
在非 Windows 平台上具有默认的句柄,其在使用代码 128 + signal number
退出之前重置终端模式。
如果这些信号之一安装了监听器,则其默认行为将被删除(Node.js 将不再退出)。'SIGPIPE'
默认情况下忽略。
它可以安装监听器。'SIGHUP'
在 Windows 上是在关闭控制台窗口时生成,在其他平台上是在各种类似条件下生成。
参见 signal(7)
。
它可以安装监听器,但是 Node.js 将在大约 10 秒后被 Windows 无条件地终止。
在非 Windows 平台上,SIGHUP
的默认行为是终止 Node.js,但一旦安装了监听器,则其默认行为将被删除。'SIGTERM'
Windows 上不支持,可以监听。'SIGINT'
,通常可以使用 Ctrl+C 生成(但是这是可配置的)。
当启用终端原始模式并使用 Ctrl+C 时不会生成它。'SIGBREAK'
在 Windows 上,当按下 Ctrl+Break 时会发送。
在非 Windows 平台上,它可以被监听,但无法发送或生成它。'SIGWINCH'
当调整控制台大小时会发送。
在 Windows 上,这只会发生在当光标移动时写入控制台,或者当在原始模式下使用可读的终端时。'SIGKILL'
不能安装监听器,它会无条件地终止所有平台上的 Node.js。'SIGSTOP'
不能安装监听器。'SIGBUS'
、'SIGFPE'
、'SIGSEGV'
和 'SIGILL'
,当没有使用 kill(2)
人为引发时,本质上会使进程处于调用 JS 监听器不安全的状态。
这样做可能会导致进程停止响应。0
可以发送来测试进程是否存在,如果进程存在则没影响,如果进程不存在则抛出错误。Windows 不支持信号,因此没有等价的使用信号来终止,但 Node.js 提供了一些对 process.kill()
和 subprocess.kill()
的模拟:
SIGINT
、SIGTERM
、和 SIGKILL
会导致目标进程无条件的终止,之后子进程会报告进程被信号终止。0
可以作为独立于平台的方式来测试进程是否存在。process.abort()
#process.abort()
方法会导致 Node.js 进程立即退出并生成一个核心文件。
此特性在 Worker
线程中不可用。
process.allowedNodeEnvironmentFlags
#process.allowedNodeEnvironmentFlags
属性是 NODE_OPTIONS
环境变量中允许的特殊的只读 Set
标志。
process.allowedNodeEnvironmentFlags
继承了 Set
,但覆盖了 Set.prototype.has
以识别几种不同的可能标志表示。
在以下情况下,process.allowedNodeEnvironmentFlags.has()
将返回 true
:
-
)或双(--
)破折号;例如,inspect-brk
代表 --inspect-brk
,或 r
代表 -r
。--v8-options
中所列)可能会替换一个或多个_非前导_破折号作为下划线,反之亦然;例如,--perf_basic_prof
、--perf-basic-prof
、--perf_basic-prof
等。=
) 字符;在第一个等号之后并包括在内的所有字符都将被忽略;例如,--stack-trace-limit=100
。NODE_OPTIONS
中是允许的。在 process.allowedNodeEnvironmentFlags
上迭代时,标志只会出现_一次_;每个都以一个或多个破折号开头。
传给 V8 的标志将包含下划线而不是非前导破折号:
import { allowedNodeEnvironmentFlags } from 'process';
allowedNodeEnvironmentFlags.forEach((flag) => {
// -r
// --inspect-brk
// --abort_on_uncaught_exception
// ...
});
const { allowedNodeEnvironmentFlags } = require('process');
allowedNodeEnvironmentFlags.forEach((flag) => {
// -r
// --inspect-brk
// --abort_on_uncaught_exception
// ...
});
process.allowedNodeEnvironmentFlags
的方法 add()
、clear()
和 delete()
什么都不做,会静默失败。
如果 Node.js 编译时_没有_ NODE_OPTIONS
支持(显示在 process.config
中),那么 process.allowedNodeEnvironmentFlags
将包含_本来_允许的内容。
process.arch
#为其编译 Node.js 二进制文件的操作系统 CPU 架构。
可能的值为:'arm'
、'arm64'
、'ia32'
、'mips'
、'mipsel'
、'ppc'
、'ppc64'
、's390'
、's390x'
、'x32'
和 'x64'
。
import { arch } from 'process';
console.log(`This processor architecture is ${arch}`);
const { arch } = require('process');
console.log(`This processor architecture is ${arch}`);
process.argv
#process.argv
属性返回数组,其中包含启动 Node.js 进程时传入的命令行参数。
第一个元素将是 process.execPath
。
如果需要访问 argv[0]
的原始值,请参阅 process.argv0
。
第二个元素将是正在执行的 JavaScript 文件的路径。
其余元素将是任何其他