nodejs全局对象简析

  • Global:全局变量
  • 定时器、控制台输出、事件
  • 模块化相关的一些全局变量
  • path/url相关的一些全局变量
  • 编码相关的
  • buffer:缓存(简单介绍)
  • Process:进程(重点解析)

 一、Global

Global与浏览器中的全局对象window的功能非常类似,可以简单的理解为提供在开发过程任意地方供调用的属性、方法、对象,不需要做任何引入创建等操作。由于nodejs是一个服务端平台而浏览器是客户端平台,它们在具体的功能上肯定有很大的差异,但也有基于JS的完全相同的一些功能。

1.1定时器、控制台输出、事件

这些都是基础的JS內置功能,这与浏览器上的window表面上没有任何差异,但由于nodejs与浏览器的实现目的差异,在底层上这些功能nodejs相比浏览器提供了更多可扩展性空间,比如控制台输出的console.log可以在基于流的基础上做很多扩展。

-- 定时器:(具体参考官方文档timers)

setImmediate(call[,..arg]):事件结束时调用异步任务

clearImmediate(immediate):用于取消setImmediate任务

//setImmediate在事件循环结束时调用(异步),可以将他理解为一个立即调用的异步任务
//返回Immediate,可以使用clearImmediate控制该回调是否保持或取消,
let imm = setImmediate(function(args){
    console.log(args);
},"事件结束后我被调用了");
clearImmediate(imm);//这里同步任务上取消了imm,所以不会调用(可以注释这一行代码看看它的执行效果)

余下的setInterval、setTimeout、clearInterval、clearTimeout这些就不用介绍了,在浏览器中都是使用非常频繁的。当然浏览器中也有Immediate的两个API,只是大部分浏览器不兼容而已。

-- 控制台输出、事件

console、Event、EventTarget这些同样在浏览器中都有,就不做过多介绍了,但后面会有博客就nodejs的事件机制做具体的分析。

1.2模块化相关的全局API

exports、module、require、require()这些在之前的这篇博客中有初步应用的介绍,如果需要了解可以查看详细内容:nodejs入门之模块。后面会有博客针对nodejs的commondjs规范做详细解析,也会包含这些API的使用。

1.3path/url

console.log(__dirname);//当前模块的目录(相对于项目的根目录)
console.log(__filename);//当前模块的文件名称(包含目录节点分隔符和后缀“\index.js”)

URL、URLSearchParams是nodejs內置的网址模块内容,在之前有一篇博客详细的分析了这部分内容:nodejs入门API之url模块+querystring模块

1.4编码相关的

在全局上有TextDecoder、TextEncoder这两个类,它们是用于处理编码相关的內置模块,后面会有详细解析nodejs编码相关的博客。

1.5buffer缓存

用于处理二进制数据,这是在nodejs中一个相对重要的内容,后面会有专门的博客解析,到之后写完再来粘贴链接。

 二、Process(进程)

process对象是提供当前nodejs进程的信息,并对其控制管理的內置全局模块。

首先在进入process具体的解析前做一些说明,由于这一篇博客重点在介绍nodejs的全局对象,所以这里只对process做基本使用的解析,不会涉及nodejs的进程管理和其原理做分析,后面会有一篇专门分析nodejs进程管理底层原理及相关的服务架构内容博客。

2.1获取当前进程的信息:cpu 、内存

-- process.memoryUsage():返回描述当前nodejs进程的内存使用量(以字节为单位)

process.memoryUsage();
//返回结果
{
    rss: 18866176,          //常驻内存大小
    heapTotal: 4014080,     //当前v8申请使用的总的内存大小
    heapUsed: 2278552,      //当前脚本实际使用的内存大小
    external: 801290,       //扩展的内存大小
    arrayBuffers: 9382      //独立的空间大小(不占用v8申请使用的内存大小)
}

RSS:常驻内存大小,是进程在主内存设备中占用的空间量,包括C++和JavaScript对象和代码,意思就是当前进程实在内存设备中分配到了多少内存供自己使用,比如示例中实际分到了18866176个字节的内存供自己使用。

heapTotal:当前v8申请使用的总的内存大小,也就是指当前进程运行实际使用了RSS多少内存,比如示例中的信息可以看到当前进程使用了常驻内存的4014080个字节,由此我们可以得出当前常驻内存还剩18866176-4014080=14852096个字节的内存没有被使用。然后我们需要知道这个使用的内存包含了当前进程的JS代码和c/c++的总内存,在前面一节nodejs入门第一节课中解析的nodejs的内部架构,除了javaScript模块还有底层的C/C++等模块,所以在memoryUsage打印的结果中还包含了heapUsed和external两个内存信息,它们分别代表JS模块和c/c++扩展模块的内存使用信息。

heapUsed:当前脚本使用的内存大小,这里我们就可以通过引入一个模块来测试这个内存信息的变化:

const fs = require('fs');
process.memoryUsage();
{
  rss: 19304448,     
  heapTotal: 4276224,
  heapUsed: 2490984, 
  external: 941238,  
  arrayBuffers: 9382 
}

你会发现当引入了fs模块后heapUsed的内存明显多出了很多:2490984-2278552=212432字节。但同时也发现external也有变化:941238-801290=139948,这是因为在引入fs模块时候node在底层就会添加与fs模块相关的C/C++模块,用来准备处理fs模块的相关对象和接口。

external:扩展内存大小,通过前面的heapUsed大概就能明白它的含义,实际上就是v8管理JavaScript对象的C/C++对象的内存使用量,所以这就是但引入fs模块后external也会增长的原因。

arrayBuffers:独立的内存空间大小,不占用v8自动申请的内存,也就是说arrayBuffers的内存不在srr的内存计算范围内。比如可以使用下面的代码申请一个独立内存,但是你会发现srr的内存也发生了变化,这跟之前引入fs模块的情况类似,这是因为v8会根据你引入的模块在底层加载相应的处理模块,并且当前脚本上还会加载Buffer相关js模块的内容,所以其他值也会跟着发生变化,关于独立内存的使用会在Buffer中介绍,后期还会有关于内存管理的博客详细解析。

Buffer.alloc(1000);    //申请独立内存空间
console.log(process.memoryUsage());

2.2运行环境:运行目录、node环境、cpu架构、用户环境、系统平台、环境标志、可配置文件、node元数据、当前node可执行文件的绝对路径

-- process.cwd():运行目录

//当前的进程的工作目录,即当前代码所在的文件的目录
console.log(process.cwd());

在node上有一个方法可以改变当前进程的工作目录:process.chdir(directory),参数就是需要更改目标目录的绝对路径字符串。

-- process.version:当前node环境,即当前执行项目的node版本号。

//当前的node环境,即当前执行项目的node的版本号
console.log(process.version);   //v14.4.0
console.log(process.versions);   //详细的node环境信息,包含了node、v8、uv、zlib、brotli、ares、modules、nghttp2、napi、llhttp、openssl、cldr、icu、tz、unicode这些底层模块的版本信息

-- process.arch:CPU架构

//CPU架构
console.log(process.arch);  //x64--即当前设备的CPU架构为64位操作系统

-- process.env:用户环境,这里包含的信息比较多,主要是一些路径信息,在前端工程中的应用主要是用来配置生产环境和开发环境。

//用户环境
console.log(process.env);
console.log(process.env.PATH);//当前本机的环境变量
console.log(process.env.USERPROFILE);   //本机管理员目录,这个信息根操作系统有关,如果是mac平台关键字就是HOME
console.log(process.env.NODE_ENV);//通常用来配置开发或生成环境信息,没有配置的情况下返回undefined

-- process.platform:系统平台

console.log(process.platform);  //win32

-- process.allowedNodeEnvironmentFlags:当前环境所有环境标志的set对象。所谓环境标志就是在使用node命令执行脚本时输入的如:node --max-old-space-size=1536 表示当前启动的node进程最大未1.5GB。详细参考官方文档的CLI命令部分。

process.allowedNodeEnvironmentFlags.forEach((flag)=>{
    console.log(flag);
});

-- process.config:当前node执行的可配置文件内容。这与运行 ./configure 脚本时生成的 config.gypi 文件相同。

console.log(process.config);

-- process.release:当前node版本相关元数据。

console.log(process.release);

-- process.execPath:当前node可执行文件的绝对路径。

2.3运行状态:启动参数、PID、运行时间、测试性能、当前进程资源的情况、更改当前进程的工作目录、当前进程debug的调试端口、设置或获取当前进程的掩码

-- process.argv:启动参数,这个属性返回一个数组,第一个元素是当前node程序所在的目录,第二个元素是当前脚本的完整路径,后面的就是启动命令时后面依次添加的参数信息,比如下面的示例:

//测试命令:node .\index.js a b
console.log(process.argv);
//打印结果:
[
    'F:\\nodejs\\node.exe',
    'E:\\node\\process进程\\index.js',
    'a',
    'b'
]

-- process.pid:当前进程的PID。

console.log(process.pid);//当前进程的PID,可以通过这个PID在任务管理器中查找到任务的相关信息

比如windows可以通过任务管理器面板查看,但要注意由于你当前的执行进程是执行后立即关闭的,那就无法查看到。如果你这时候启动了对一个端口的监听,程序没有关闭就可以查看到。除了直接在任务管理器面板中查看还可以通过控制台查看,具体操作就不演示了。

 

-- process.title:当前进程的标题。即上面截图的名称值,也可以通过该属性自定义名称,注意标题在部分系统下有长度限制。

 -- process.ppid:当前进程的父进程PID。这篇博客没有介绍子进程,就不演示了了,在后期的nodejs进程管理的博客中会有具体的应用何解析。

-- process.uptime():当前进程运行的秒数(注意这个时间单位是“秒”)。

setTimeout(()=>{
    console.log(process.uptime());  //当前进程的执行时间(单位:秒)
},3000);

--process.cpuUsage([previousValue]):但概念进程的用户代码和系统代码分别在CPU上运行的时间,参数previousValue就是这个方法的返回值,当传入这个参数时该方法会得到减去传入值的返回值,意思就是当前这段执行用户代码和系统代码在CPU上运行的时间,返回数据单位为毫秒。

let startUsage = process.cpuUsage();
console.log(startUsage);
let now = Date.now();
while (Date.now() - now < 500);
console.log(process.cpuUsage(startUsage));
console.log(process.cpuUsage());

--process.hrtime.bigint():当前进程运行的时间(高解析度:纳秒)

 1 //这些时间相对于过去的任意时间,与一天中的时间无关,因此不受时钟漂移的影响。 主要用途是测量间隔之间的性能
 2 import { hrtime } from 'process';
 3 
 4 const start = hrtime.bigint();
 5 // 191051479007711n
 6 
 7 setTimeout(() => {
 8   const end = hrtime.bigint();
 9   // 191052633396993n
10 
11   console.log(`Benchmark took ${end - start} nanoseconds`);
12   // 基准测试耗时 1154389282 纳秒
13 }, 1000);
View Code

--process.resourceUsage():当前进程资源的情况,比如使用的内存容量、用户代码使用cpu时间、系统代码使用的cpu时间等。

console.log(process.resourceUsage());   //当前进程资源的情况

-- process.chdir(directory);//更改当前进程的工作目录。

-- process.debugPort:设置node启动debug的调试端口,可以通过改属性获取或设置debug的端口。

-- process.umask(mask):设置或获取当前进程的掩码。

1 import { umask } from 'process';
2 
3 const newmask = 0o022;
4 const oldmask = umask(newmask);
5 console.log(
6   `Changed umask from ${oldmask.toString(8)} to ${newmask.toString(8)}`
7 );
View Code

2.4进程事件:

-- exit:退出当前进程事件。

process.on('exit',(code)=>{ //当进程退出时触发该事件回调。code为事件状态码。
    console.log('exit:' + code);
});

进程退出状态码:默认状态码为0,该状态码可以通过process.exit(code)主动退出进程来设置,还可以通过process.exitCode属性来设置退出状态码。

退出当前进程的三种情况:事件循环不在需要执行任何额外工作自动退出进程、使用process.exit()结束进程的显式调用手动退出进程、使用process.abort()退出文件,这个方法退出进程不会触发exit事件,但会生成一个核心文件。

process.abort();//退出当前进程并生成一个核心文件,但要注意的是不会触发exit事件

注意:退出当前进程事件回调中不能使用异步任务,因为主进程结束后使得事件循环中排队的其他工作会被丢弃。

-- beforeExit:退出当前进程前的事件任务。

process.on('beforeExit',(code)=>{//在进程退出前触发该事件回调,code为事件状态码
    console.log('befor exit:'+ code);
});

这个回调同样会接收到退出状态码,与exit事件差不多,但需要特别注意的是这个回调内部如果使用了异步任务,会导致进程无法退出,这是因为当你每一次执行完beforeExit异步任务后,主进程又启动了新的beforeExit任务。

-- message:进程消息事件,即两个进程之间通过process.send()向另一个经常发送消息时,另一个接收消息的message事件被触发,message事件回调接收的参数就是send传入的实参。假设现在有一个主进程parent.js和子进程sub.js如下方示例:

 1 //parent.js --主线程
 2 const cp = require('child_process');    //引入子进程模块
 3 let n = cp.fork(__dirname + '/sub.js'); //通过fork加载子进程sub.js
 4 n.on('message',function(m){             //在主进程上注册一个监听子进程sub.js的send发来的消息
 5     console.log('PARENT got message:' , m);
 6 });
 7 n.send({hello:'world'});                //在主进程上给子线程sub.js发送消息
 8 
 9 //sub.js -- 子进程
10 process.on('message',function(m){        //注册一个监听父进程send发送来的消息事件
11     console.log('CHILD got message:',m);
12 });
13 
14 process.send({foo:'bar'});               //向父进程发送消息

关于process上的message事件有几个相关的API和模块:

process.send():负责向子进程发送消息;

process.on('message',fun):负责监听父级进程的send发送过来的消息;

child_process:子进程模块;

child_processObj.fork():创建子进程,在child_process模块上创建子进程的方法总共有四个,这里展示不介绍了,在后面的nodejs进程管理那篇博客中具体的解析。

child_processObj.send():在主进程上向子进程child_processObj发送消息;

child_processObj.on('message', fun):在主进程上监听子进程child_processObj通过send发送过来的消息。

这里需要注意,在示例中的主进程和子进程上的message事件触发没有先后顺序,这是因为它们分属不同的进程,它们通过send发出的消息都会被丢到事件轮询管理机制内,然后再有事件轮询机制响应给它们然后触发它们的事件回调任务,这个现后顺序简单的说一个随机概率,严格来说是要看它们的进程什么时候收到事件轮询机制的响应。(所以你可以通过多次启动主进程来查看打印结果,绝对会出现打印先后顺序不一致的情况)

-- disconnect:关闭与父级进程的通信通道事件,该方法由子进程上的process.disconnect()或父级进程下的child_processObj.disconnect()关闭与父级进程的通信通道时触发。比如还是使用上面的主进程parent.js和子进程sub.js示例:

 1 //parent.js -- 主进程
 2 const cp = require('child_process');    //引入子进程模块
 3 let n = cp.fork(__dirname + '/sub.js'); //通过fork加载子进程sub.js
 4 n.on('message',function(m){             //在主进程上注册一个监听子进程sub.js的send发来的消息
 5     console.log('PARENT got message:' , m);
 6     n.disconnect();                     //在主进程上关闭子进程sub.js与父级parent.js(当前主进程)的通信通道
 7 });
 8 n.send({hello:'world'});                //在主进程上给子线程sub.js发送消息
 9 
10 //sub.js -- 子进程
11 process.on('message',function(m){       //注册一个监听父进程send发送来的消息事件
12     console.log('CHILD got message:',m);
13     process.disconnect();               //在子进程上关闭与父进程的通信通道
14 });
15 process.on('disconnect',function(){
16     console.log('子进程sub.js与父进程通信通道关闭');
17 });
18 process.send({foo:'bar'});              //向父进程发送消息

2.5监听promise的一些风险行为的事件(这依然是process上的事件)

-- multipleResolves事件:用于解决在Promise构造中可能出现的潜在错误问题,当Promise构造中出现这四种情况时,该事件会被触发。

第一种情况:解决多次,即在Promise构造中一个逻辑下出现多次调用resole,以下示例:

 1 process.on('multipleResolves',(type,promise,reason)=>{
 2     console.error(type,promise,reason);
 3 });
 4 function main(){
 5     return  new Promise((resole, reject) => {
 6         resole("First call");
 7         resole('Swallowed resolve');
 8     });
 9 }
10 main().then(console.log,console.log);
11 //打印结果
12 //multipleResolves事件被触发: resolve Promise { 'First call' } Swallowed resolve
13 //then的解决受理:First call

第二种情况:拒绝多次,即在Promise构造中一个逻辑下出现多次调用reject,以下示例:

 1 process.on('multipleResolves',(type,promise,reason)=>{
 2     console.error(type,promise,reason);
 3     // setImmediate(()=> process.exit(1));
 4 });
 5 
 6 function main(){
 7     return  new Promise((resole, reject) => {
 8         reject('First reject');
 9         reject('Swallowed reject');
10     });
11 }
12 main().then(console.log,console.log);
13 //打印结果
14 //multipleResolves事件被触发:reject Promise { <rejected> 'First reject' } Swallowed reject
15 //then的拒绝受理:First reject

第三种情况:解决又拒绝,即在Promise构造中一个逻辑下出现先调用了resole又在后面调用了reject,以下示例:

 1 process.on('multipleResolves',(type,promise,reason)=>{
 2     console.error(type,promise,reason);
 3 });
 4 
 5 function main(){
 6     return  new Promise((resole, reject) => {
 7         resole("First call");
 8         reject('First reject');
 9     });
10 }
11 main().then(console.log,console.log);
12 //打印结果
13 //multipleResolves事件被触发:reject Promise { 'First call' } First reject
14 //then的解决受理:First call

第四种情况:拒绝又解决:即在Promise构造中一个逻辑下出现了先调用了reject又在后面调用了resole,以下示例:

 1 process.on('multipleResolves',(type,promise,reason)=>{
 2     console.error(type,promise,reason);
 3 });
 4 
 5 function main(){
 6     return  new Promise((resole, reject) => {
 7         reject('First reject');
 8         resole("First call");
 9     });
10 }
11 main().then(console.log,console.log);
12 //打印结果
13 //multipleResolves事件被触发:resolve Promise { <rejected> 'First reject' } First call
14 //then的拒绝受理:First reject

-- rejectionHandled事件:当promise延后调用catch捕获错误时,会触发该事件,在官方文档中的描述是晚一轮

 1 process.on('rejectionHandled',function(promise){
 2     console.log('catch没有及时触发',promise);
 3 });
 4 
 5 let oP = new Promise((resolve, reject) => {
 6     reject(new Error("no"));
 7 });
 8 // oP.catch((err) => {  //同步代码的cathc捕获不会触发rejectionHandled事件
 9 //     console.log("异常捕获:" + err.toString());
10 // });    
11 setTimeout(()=>{    //异步导致的延后会触发rejectionHandled事件
12     oP.catch((err) => {
13         console.log("异常捕获:",err.toString());
14     });    
15 });

-- unhandledRejection事件:当promise中reject的异常在同步任务中没有使用catch捕获就会触发该事件,即便是在异步情况下使用了catch也会触发该事件(如上面rejectionHandled事件的示例情况)。

 1 // process.on('rejectionHandled',function(promise){
 2 //     console.log('catch没有及时触发');
 3 // });
 4 process.on('unhandledRejection',function(reason, promise){
 5     console.log("---------------");
 6 });
 7 
 8 let op = new Promise((resolve,reject)=>{
 9     reject(new Error("no"));
10 });
11 // setTimeout(()=>{
12 //     op.catch((err)=>{
13 //         console.log('异常捕获:');
14 //     })
15 // })

2.6监听未捕获异常的一些事件:

-- uncaughtExceptionMonitor:当进程上抛出异常而没有被捕获时触发该事件。

-- uncaughtException:当进程上抛出异常而没有被捕获时触发该事件,并且使异常静默。

需要注意的是异步任务中的异常同样可以被捕获,但是Pormise中未捕获的异常不能触发这两个事件,Pormise的未捕获异常由前面介绍的rejectionHandled和unhandledRejection监听。

 1 process.on('uncaughtExceptionMonitor',function(err, origin){
 2     console.log("监听到当前进程上出现未捕获的异常");
 3 });
 4 process.on('uncaughtException',function(err, origin){
 5     console.log('监听到当前进程上出现未捕获的异常,并静默该异常');  //静默异常表示被监听到的异常不会被抛出
 6 });
 7 function fu(){
 8     throw new Error('fu');
 9 }
10 // setTimeout(()=>{
11 //     fu();
12 // });
13 fu();
14 
15 //当异常被捕获,则uncaughtExceptionMonitor 、uncaughtException事件不会被触发
16 // try{
17 //     fu();
18 // }catch(err){
19 //     console.log(err.toString());
20 // }

关于异常还有一个方法:process.setUncaughtExceptionCaptureCallback(fn),这个方法的功能与uncaughtException一致,并且会导致uncaughtException事件不会被触发。这个方法的使用方式就是传入一个回调函数,这个回调函数接收到错误对象作为参数。它同样具有静默异常的功能。

 1 process.setUncaughtExceptionCaptureCallback(function(err){
 2     console.log('---------------');
 3     console.log(err.toString());
 4 });
 5 process.on('uncaughtExceptionMonitor',function(err, origin){
 6     console.log("监听到当前进程上出现未捕获的异常");
 7 });
 8 process.on('uncaughtException',function(err, origin){
 9     console.log('监听到当前进程上出现未捕获的异常,并静默该异常');  //静默异常表示被监听到的异常不会被抛出
10 });
11 function fu(){
12     throw new Error('fu');
13 }
14 fu();
View Code

并且还可以通过process.hasUncaughtExceptionCaptureCallback()方法来检测当前是否使用process.setUncaughtExceptionCaptureCallback(fn)方法,该方法返回一个boolean值。

2.7监听进程警告的事件和触发警告的方法:warning、emitwarning

 1 process.on('warning',function(warning){    //监听警告
 2     console.log('进程警告:');
 3     console.log('名称:' + warning.name);
 4     console.log('信息:' + warning.message);
 5     console.log('堆栈:' + warning.stack);
 6 });
 7 process.emitWarning('Something happened!',{    //触发警告
 8     type:'第一个警告',
 9     code:'MY_WARNING',
10     detail:'This is some additional in formation'
11 });

触发警告的方法有三种参数形式:

process.emitWarning(warning[, options])
process.emitWarning(warning[, type[, code]][, ctor])
process.emitWarning(Error);

2.8创建独立线程时触发worker事件,详细在后面会有专门的博客解析关于worker模块的内容。

2.9在当前js任务堆栈后,事件轮询前添加一个堆栈任务:

-- process.nextTick(callback[, ...args]);

 1 console.log('start');
 2 process.nextTick(function(){
 3     console.log('nextTick callback');
 4 });
 5 setTimeout(function(){
 6     console.log('setTimeout');
 7 });
 8 console.log('scheduled');
 9 // start
10 // scheduled
11 // nextTick callback
12 // setTimeout

注意的是如果在process.nextTick内部添加process.nextTick会导致死循环,在异步堆栈上同样可以使用:

 1 console.log('start');
 2 process.nextTick(function(){
 3     console.log('nextTick callback1');
 4 });
 5 setTimeout(function(){
 6     console.log('setTimeout1');
 7     process.nextTick(function(){
 8         console.log('nextTick callback2');
 9     });
10     console.log('setTimeout2');
11 });
12 console.log('scheduled');
13 // start
14 // scheduled
15 // nextTick callback1
16 // setTimeout1
17 // setTimeout2
18 // nextTick callback2

-- queueMicrotask():这是全局上的一个实现添加堆栈的方法,这个方法使用来替代process.nextTick方法的,但需要注意它与process.nextTick、Promise堆栈的执行顺序。

 1 setTimeout(()=>{
 2     console.log('4');
 3 });
 4 console.log('a');
 5 Promise.resolve().then(() => console.log(2));
 6 console.log('b');
 7 queueMicrotask(() => console.log(3));
 8 console.log('c');
 9 process.nextTick(() => console.log(1));
10 console.log('d');
11 //a b c d 1 2 3 4

但是queueMicrotask()只能接收一个回调函数,不能像process.nextTick那样直接在后面添加参数,为了解决这个问题参考下面这个来自官方的示例:

 1 function deferred(a, b) {
 2   console.log('microtask', a + b);
 3 }
 4 console.log('start');
 5 queueMicrotask(deferred.bind(undefined, 1, 2));
 6 console.log('scheduled');
 7 // 输出:
 8 // start
 9 // scheduled
10 // microtask 3

2.10关于进程上的流相关API的应用,可以参考基于node实现一个简单的脚手架工具(node控制台交互项目),后面会有关于流更详细的解析博客。

process上流的API有:

process.stderr
process.stderr.fd
process.stdin
process.stdin.fd
process.stdout
process.stdout.fd

//通过控制台输入流的API
process.stdin.resume();
1 #!/usr/bin/env node
2 
3 process.stdout.write('\033[33m输入:\033[39');
4 process.stdin.resume(); //等待输入
5 process.stdin.setEncoding('utf-8');
6 process.stdin.on('data',function(data){
7     process.stdin.pause();
8     console.log('\033[90m输入的内容是:' + data + '\033[39m');
9 })
这是来自手脚那篇博客的实例应用代码

2.11与IPC通道相关的API:

还记得在前面message事件中讲过进程之间的通信,node进程通信就是基于IPC通道,但这里不作详细的解释,后面的node进程管理会有详细的解析,这里只看在Process上提供的API。

-- process.channel:IPC通道的衍生,是对子进程IPC通道的引用。在主进程上没有该属性所以返回值为undefined。

-- process.connected:改属性表示当前进程的IPC通道是否建立连接,如果连接建立了就返回true,否则返回false。但如果当前进程没有启动IPC通道则返回undefiend。
-- process.kill(pid):用来杀死指定进程,如果指定的进程pid不存在则会报错,官方文档中说可以传入第二个参数作为信号事件,但测试第二个参数就报错。

2.12当前进程诊断报告的相关API

 1 process.report:管理诊断报告的对象;
 2 process.report.compact:用于设置诊断包括是否以JSON格式,改属性值类型<Boolean>,默认false;
 3 process.report.directory:用于设置保存诊断报告的路径,默认值为空,表示将报告写入工作目录;
 4 process.report.filename:写入报告的文件名。 如果设置为空字符串,则输出文件名将由时间戳、PID 和序列号组成。 默认值为空字符串;
 5 process.report.getReport([err]):返回正在运行的进程的诊断报告的 JavaScript 对象表示形式。 报告的 JavaScript 堆栈跟踪取自 err(如果存在)。
 6 process.report.reportOnFatalError:如果为 true,则会生成有关致命错误(例如内存不足错误或 C++ 断言失败)的诊断报告。
 7 process.report.reportOnSignal:如果为 true,则当进程接收到 process.report.signal 指定的信号时生成诊断报告。
 8 process.report.reportOnUncaughtException:如果为 true,则针对未捕获的异常生成诊断报告。
 9 process.report.signal:用于触发诊断报告创建的信号。 默认为 'SIGUSR2'。
10 process.report.writeReport([filename][, err]):将诊断报告写入文件。 如果未提供 filename,则默认文件名包括日期、时间、PID 和序列号。 报告的 JavaScript 堆栈跟踪取自 err(如果存在)。

测试生成诊断报告:

process.report.reportOnUncaughtException = true;
throw new Error('诊断报告');
posted @ 2022-03-06 15:05  他乡踏雪  阅读(517)  评论(0编辑  收藏  举报