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);
--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 );
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();
并且还可以通过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('诊断报告');