详解Node.JS模块 process


Posted in Javascript onAugust 31, 2020

process 模块是 nodejs 提供给开发者用来和当前进程交互的工具,它的提供了很多实用的 API。从文档出发,管中窥豹,进一步认识和学习 process 模块:

  • 如何处理命令参数?
  • 如何处理工作目录?
  • 如何处理异常?
  • 如何处理进程退出?
  • process 的标准流对象
  • 深入理解 process.nextTick

如何处理命令参数?

命令行参数指的是 2 个方面:

  • 传给 node 的参数。例如 node --harmony script.js --version 中,--harmony 就是传给 node 的参数
  • 传给进程的参数。例如 node script.js --version --help 中,--version --help 就是传给进程的参数

它们分别通过 process.argvprocess.execArgv 来获得。

如何处理工作目录?

通过process.cwd()可以获取当前的工作目录。

通过process.chdir(directory)可以切换当前的工作目录,失败后会抛出异常。实践如下:

function safeChdir(dir) {
 try {
  process.chdir(dir);
  return true;
 } catch (error) {
  return false;
 }
}

如何处理异常?

uncaughtException 事件

Nodejs 可以通过 try-catch 来捕获异常。如果异常未捕获,则会一直从底向事件循环冒泡。如是冒泡到事件循环的异常没被处理,那么就会导致当前进程异常退出。

根据文档,可以通过监听 process 的 uncaughtException 事件,来处理未捕获的异常:

process.on("uncaughtException", (err, origin) => {
 console.log(err.message);
});

const a = 1 / b;
console.log("abc"); // 不会执行

上面的代码,控制台的输出是:b is not defined。捕获了错误信息,并且进程以0退出。开发者可以在 uncaughtException 事件中,清除一些已经分配的资源(文件描述符、句柄等),不推荐在其中重启进程。

unhandledRejection 事件

如果一个 Promise 回调的异常没有被.catch()捕获,那么就会触发 process 的 unhandledRejection 事件:

process.on("unhandledRejection", (err, promise) => {
 console.log(err.message);
});

Promise.reject(new Error("错误信息")); // 未被catch捕获的异常,交由unhandledRejection事件处理

warning 事件

告警不是 Node.js 和 Javascript 错误处理流程的正式组成部分。 一旦探测到可能导致应用性能问题,缺陷或安全隐患相关的代码实践,Node.js 就可发出告警。

比如前一段代码中,如果出现未被捕获的 promise 回调的异常,那么就会触发 warning 事件。

如何处理进程退出?

process.exit() vs process.exitCode

一个 nodejs 进程,可以通过 process.exit() 来指定退出代码,直接退出。不推荐直接使用 process.exit(),这会导致事件循环中的任务直接不被处理,以及可能导致数据的截断和丢失(例如 stdout 的写入)。

setTimeout(() => {
 console.log("我不会执行");
});

process.exit(0);

正确安全的处理是,设置 process.exitCode,并允许进程自然退出。

setTimeout(() => {
 console.log("我不会执行");
});

process.exitCode = 1;

beforeExit 事件

用于处理进程退出的事件有:beforeExit 事件 和 exit 事件。

当 Node.js 清空其事件循环并且没有其他工作要安排时,会触发 beforeExit 事件。例如在退出前需要一些异步操作,那么可以写在 beforeExit 事件中:

let hasSend = false;
process.on("beforeExit", () => {
 if (hasSend) return; // 避免死循环

 setTimeout(() => {
  console.log("mock send data to serve");
  hasSend = true;
 }, 500);
});

console.log(".......");
// 输出:
// .......
// mock send data to serve

注意:在 beforeExit 事件中如果是异步任务,那么又会被添加到任务队列。此时,任务队列完成所有任务后,又回触发 beforeExit 事件。因此,不处理的话,可能出现死循环的情况。如果是显式调用 exit(),那么不会触发此事件。

exit 事件

在 exit 事件中,只能执行同步操作。在调用 ‘exit' 事件监听器之后,Node.js 进程将立即退出,从而导致在事件循环中仍排队的任何其他工作被放弃。

process 的标准流对象

process 提供了 3 个标准流。需要注意的是,它们有些在某些时候是同步阻塞的(请见文档)。

  • process.stderr:WriteStream 类型,console.error的底层实现,默认对应屏幕
  • process.stdout:WriteStream 类型,console.log的底层实现,默认对应屏幕
  • process.stdin:ReadStream 类型,默认对应键盘输入

下面是基于“生产者-消费者模型”的读取控制台输入并且及时输出的代码:

process.stdin.setEncoding("utf8");

process.stdin.on("readable", () => {
 let chunk;
 while ((chunk = process.stdin.read()) !== null) {
  process.stdout.write(`>>> ${chunk}`);
 }
});

process.stdin.on("end", () => {
 process.stdout.write("结束");
});

关于事件的含义,还是请看stream 的文档。

深入理解 process.nextTick

我第一次看到 process.nextTick 的时候是比较懵的,看文档可以知道,它的用途是:把回调函数作为微任务,放入事件循环的任务队列中。但这么做的意义是什么呢?

因为 nodejs 并不适合计算密集型的应用,一个进程就一个线程,在当下时间点上,就一个事件在执行。那么,如果我们的事件占用了很多 cpu 时间,那么之后的事件就要等待非常久。所以,nodejs 的一个编程原则是尽量缩短每一个事件的执行事件。process.nextTick 的作用就在这,将一个大的任务分解成多个小的任务。示例代码如下:

// 被拆分成2个函数执行
function BigThing() {
 doPartThing();

 process.nextTick(() => finishThing());
}

在事件循环中,何时执行 nextTick 注册的任务呢?请看下面的代码:

setTimeout(function() {
 console.log("第一个1秒");
 process.nextTick(function() {
  console.log("第一个1秒:nextTick");
 });
}, 1000);

setTimeout(function() {
 console.log("第2个1秒");
}, 1000);

console.log("我要输出1");

process.nextTick(function() {
 console.log("nextTick");
});

console.log("我要输出2");

输出的结果如下,nextTick 是早于 setTimeout:

我要输出1
我要输出2
nextTick
第一个1秒
第一个1秒:nextTick
第2个1秒

在浏览器端,nextTick 会退化成 setTimeout(callback, 0)。但在 nodejs 中请使用 nextTick 而不是 setTimeout,前者效率更高,并且严格来说,两者创建的事件在任务队列中顺序并不一样(请看前面的代码)。

以上就是详解Node.JS模块 process的详细内容,更多关于Node.JS模块 process的资料请关注三水点靠木其它相关文章!

Javascript 相关文章推荐
Jsonp 跨域的原理以及Jquery的解决方案
May 18 Javascript
js取得url地址参数实例
Feb 22 Javascript
页面加载完成后再执行JS的jquery写法以及区别说明
Feb 22 Javascript
JavaScript验证18位身份证号码最后一位正确性的实现代码
Aug 07 Javascript
使用iojs的jsdom库实现同步系统时间
Apr 20 Javascript
Summernote实现图片上传功能的简单方法
Jul 11 Javascript
详解AngularJs中$sce与$sceDelegate上下文转义服务
Sep 21 Javascript
js原生日历的实例(推荐)
Oct 31 Javascript
three.js实现3D视野缩放效果
Nov 16 Javascript
React组件内事件传参实现tab切换的示例代码
Jul 04 Javascript
微信小程序蓝牙连接小票打印机实例代码详解
Jun 03 Javascript
vue watch监控对象的简单方法示例
Jan 07 Vue.js
谈谈JavaScript令人迷惑的==与+
Aug 31 #Javascript
vue自定义指令限制输入框输入值的步骤与完整代码
Aug 30 #Javascript
JS性能优化实现方法及优点进行
Aug 30 #Javascript
如何检测JavaScript中的死循环示例详解
Aug 30 #Javascript
JavaScript中CreateTextFile函数
Aug 30 #Javascript
详解vue组件之间的通信
Aug 30 #Javascript
如何阻止移动端浏览器点击图片浏览
Aug 29 #Javascript
You might like
php实现文件下载(支持中文文名)
2013/12/04 PHP
php计算title标题相似比的方法
2015/07/29 PHP
PHP简单操作MongoDB的方法(安装及增删改查)
2016/05/26 PHP
php 5.4 全新的代码复用Trait详解
2017/01/05 PHP
PHP实现打包下载文件的方法示例
2017/10/07 PHP
PHP的静态方法与普通方法用法实例分析
2019/09/26 PHP
js创建子窗口并且回传值示例代码
2013/07/02 Javascript
解决window.opener=null;window.close(),只支持IE6不支持IE7,IE8的问题
2014/01/14 Javascript
js实现显示当前状态的导航效果代码
2015/08/28 Javascript
JS 设置Cookie 有效期 检测cookie
2017/06/15 Javascript
利用yarn代替npm管理前端项目模块依赖的方法详解
2017/09/04 Javascript
详解Vue基于 Nuxt.js 实现服务端渲染(SSR)
2018/04/05 Javascript
JavaScript中常见内置函数用法示例
2018/05/14 Javascript
Bootstrap Table列宽拖动的方法
2018/08/15 Javascript
对angularJs中controller控制器scope父子集作用域的实例讲解
2018/10/08 Javascript
浅谈javascript事件环微任务和宏任务队列原理
2020/09/12 Javascript
Vue时间轴 vue-light-timeline的用法说明
2020/10/29 Javascript
Python数据可视化教程之Matplotlib实现各种图表实例
2019/01/13 Python
详解如何用TensorFlow训练和识别/分类自定义图片
2019/08/05 Python
Python PO设计模式的具体使用
2019/08/16 Python
pytorch中的embedding词向量的使用方法
2019/08/18 Python
浅谈JupyterNotebook导出pdf解决中文的问题
2020/04/22 Python
Python-jenkins 获取job构建信息方式
2020/05/12 Python
pytorch快速搭建神经网络_Sequential操作
2020/06/17 Python
CSS3教程(7):CSS3嵌入字体
2009/04/02 HTML / CSS
HTML5拖放API实现自动生成相框功能
2020/04/07 HTML / CSS
基本款天堂:Everlane
2017/05/13 全球购物
您的健身减肥和健康饮食专家:vitafy
2017/06/06 全球购物
墨西哥购物网站:Elektra
2020/01/21 全球购物
法律专业应届本科毕业生求职信
2013/10/25 职场文书
办理居住证介绍信
2014/01/15 职场文书
带薪年假请假条
2014/02/04 职场文书
幼儿园毕业家长感言
2014/02/10 职场文书
女性健康知识讲座通知
2015/04/23 职场文书
开学典礼致辞
2015/07/29 职场文书
关于分班的感言
2015/08/04 职场文书