深入了解Node.js中的一些特性


Posted in Javascript onSeptember 25, 2014

Node.js作为一门新兴的后台语言,旨在帮助程序员快速构建可伸缩的应用程序。Node.js有很多吸引人的地方,有关它的报道不计其数,本文将针对EventEmitter、Streams、Coding Style、Linting、Coding Style等特性进行分析探讨,帮助用户对Node.js有更深入的了解。

作为一个基于Chrome JavaScript 运行时建立的平台,我们对JavaScript 的相关认识,似乎都可应用于node应用程序之上;无需额外的语言扩展或修饰,我们便可以把前端编程的经验应用于后端编程。

EventEmitter(事件发送器)

首先应该先了解EventEmitter模型。它可以发送一个事件以及让消费者订阅感兴趣的事件。我们可以把它看成是向一个异步函数进行回调传递模式的扩展。特别是,当需要进行多次回调时,EventEmitter会更显优势。

例如,有一个调用者向远程服务器发送了一个“列出文件”的请求。你可能想对返回结果进行分组,对每一个分组进行一次回调处理。EventEmitter模型可以让你在每一个分组上发送“文件”回调,当全部操作完成时进行“结束”处理。

使用EventEmitter时,只需设置好相关事件和参数。

var EventEmitter = require('events').EventEmitter;  

var util = require('util');  

  

function MyClass() {  

  if (!(this instanceof MyClass)) return new MyClass();  

  

  EventEmitter.call(this);  

  

  var self = this;  

  setTimeout(function timeoutCb() {  

    self.emit('myEvent', 'hello world', 42);  

  }, 1000);  

}  

util.inherits(MyClass, EventEmitter); 

MyClass构造函数创建了一个时间触发器,触发延时为1s,触发事件为myEvent。要使用相关事件,需要执行on()方法:

var myObj = new MyClass();  

var start = Date.now();  

myObj.on('myEvent', function myEventCb(str, num) {  

  console.log('myEvent triggered', str, num, Date.now() - start);  

}); 

这里要注意的是,订阅的EventEmitter事件虽然是异步事件,但当时间触发时,监听方的动作是会同步的。因此如果上述myEvent事件有10个监听者,所有的监听会被按次序调用而不用等候事件的循环。

如果EventEmitter的一个子类生成了一个emit(‘error')事件,但是无任何的监听方对此进行订阅,那么EventEmitter基类会抛出一个异常,从而导致当执行process对象时触发uncaughtException事件。

verror

verror是基类Error的扩展,可以让我们使用printf字符格式定义输出消息。

Streams(流)

如果有一个非常庞大的文件需要处理,理想的方法应该是读一部分,写一部分,不管文件有多大,只要时间允许,总会处理完成,这里就需要用到流的概念。Streams是Node中另一个广泛使用的模型,在Node中是EventEmitter的实现。提供了可读、可写或者是全双工接口。它是一个抽象接口,提供的常规操作事件包括:readable、writable、 drain、data、 end及close。如果我们能够使用pipeline(管道)来对这些事件进行有效整合,将可实现功能更强大的交互操作。

透过使用.pipe(),可以让Note通过pipeline与back-pressure进行通信。back-pressure的意思是:只读取那些能够写入的,或只写入那些能够读取的。

例如我们现在把来自stdin的数据发送到一个本地文件和远程服务器:

var fs = require('fs');

var net = require('net');
var localFile = fs.createWriteStream('localFile.tmp');
net.connect('255.255.255.255', 12345, function(client) {

  process.stdin.pipe(client);

  process.stdin.pipe(localFile);

});

而如果我们想发送数据到一个本地文件,并想使用gunzip对这个stream进行压缩,可以这样做:

var fs = require('fs');

var zlib = require('zlib');
process.stdin.pipe(zlib.createGunzip()).pipe(fs.createWriteStream('localFile.tar'));

如果想对stream有更多了解,请点击这里。

Control Flow(流程控制)

由于JS中有第一类对象,闭包等功能概念,因而能够容易地对回调权限进行定义。这在进行原型设计时是非常方便的,能够对逻辑权限按需进行整合。但是同时容易造成使用笨拙的内置函数。

例如我们想按次序读入一系列文件,然后执行某个任务:

fs.readFile('firstFile', 'utf8', function firstCb(err, firstFile) {

  doSomething(firstFile);

  fs.readFile('secondFile', 'utf8', function secondCb(err, secondFile) {

    doSomething(secondFile);

    fs.readFile('thirdFile', 'utf8', function thirdCb(err, thirdFile) {

      doSomething(thirdFile);

    });

  });

});

这个模式存在的问题是:

1.这些代码的逻辑非常散乱无序,相关的操作流程难以理解。
2.没有任何差错或异常处理。
3.JS中闭包内存泄漏是非常常见的,并难以诊断和探测。

如果我们想在一个输入集上进行一系列异步操作,使用一个流程控制库是更明智的选择。这里使用的是vasync。

vasync是一个流程控制库,其思路来源于异步操作。它的特别之处是能够让消费者对某个任务处理过程进行查看和观察。这些信息对研究某个错误的产生过程是非常有用的。

Coding Style(编程风格)

编程风格可谓最具争议性的话题,因为很多时候都是随性的。萝卜白菜,各有所爱。重要的是找到适合个人和团队的风格。一些传统的传承或许能够让Node开发之旅变得更美好。

1.为函数命名
2.尽量对所有函数进行命名。
3.避免闭包
4.不要在某个函数中定义其它函数。这可减少很多想不到的闭包内存泄露意外。
5.更多和更小巧的函数

V8 JIT虽然是一个功能强大的引擎,但是更小巧和精简的函数会与V8结合得更好。进一步说,如果我们的函数都是小巧玲珑的(100行左右),我们自己进行阅读和维护时也会感谢自己的。

用编程方式检查风格:保持风格一致性,并使用一个检查工具来加强。我们使用的是jsstyle。

Linting(代码检查)

Lint工具可以在不运行情况下进行代码的静态分析,检查出潜在的错误和风险,例如在caseswitch中遗漏了break语句。Lint不简单地等同于风格检查,它更针对于客观的风险分析,而不是主观的风格选择。我们使用的javascriptlint,它里面有丰富检查项目。

Logging(日志记录)

当我们进行程序设计和编码时,需要有长远的目光。特别是要考虑好使用什么工具来进行调试。极好的第一步是进行有效日志记录。我们需要对信息进行识别,看看什么是调试时特别留意的,什么是运行时用来分析研究的。这里推荐使用Bunyan,一个直接的Node.js日志记录库,数据输出格式是JSON ,要了解更多信息,请点击这里。

Client Server

如果一款应用具备分布式处理能力,在市场上会更有吸引力。类似的接口可以用HTTP RESTFul API或原始的TCP JSON来描述。这可以让开发者把Node上的经验与异步网络环境相结合,以及把streams的使用与分布式可扩展式系统相结合。

常用工具:

1. restify

简单来说,这是一个用于构建REST服务的工具。它提供了良好的查看和调试处理支援,同时支持Bunyan与DTrace。

2. fast

fast是一款以TCP来处理JSON消息的轻量级工具。提供了DTrace支持,能够让我们迅速地对服务器客户端进行性能特征识别。

3. workflow

workflow构建于restify之上,能够对一系列远程服务和API进行业务流程定义。例如:错误状态,超时,重新连接,拥塞处理等。

Javascript 相关文章推荐
通过MSXML2自动获取QQ个人头像及在线情况(给初学者)
Jan 22 Javascript
js 获取(接收)地址栏参数值的方法
Apr 01 Javascript
使用javascript过滤html的字符串(注释标记法)
Jul 08 Javascript
网页中可关闭的漂浮窗口实现可自行调节
Aug 20 Javascript
js控制文本框只能输入中文、英文、数字与指定特殊符号的实现代码
Sep 09 Javascript
简单实现JS倒计时效果
Dec 23 Javascript
JS实现静态页面搜索并高亮显示功能完整示例
Sep 19 Javascript
angularjs手动识别字符串中的换行符方法
Oct 02 Javascript
小程序getLocation需要在app.json中声明permission字段
Apr 04 Javascript
vue组件中watch props根据v-if动态判断并挂载DOM的问题
May 12 Javascript
如何使用CSS3+JQuery实现悬浮墙式菜单
Jun 18 jQuery
Vue初始化中的选项合并之initInternalComponent详解
Jun 11 Javascript
从JQuery源码分析JavaScript函数的apply方法与call方法
Sep 25 #Javascript
JS小游戏之仙剑翻牌源码详解
Sep 25 #Javascript
JS小游戏之宇宙战机源码详解
Sep 25 #Javascript
JS小游戏之极速快跑源码详解
Sep 25 #Javascript
JS小游戏之象棋暗棋源码详解
Sep 25 #Javascript
我用的一些Node.js开发工具、开发包、框架等总结
Sep 25 #Javascript
jquery中使用循环下拉菜单示例代码
Sep 24 #Javascript
You might like
探讨:array2xml和xml2array以及xml与array的互相转化
2013/06/24 PHP
php异步:在php中使用fsockopen curl实现类似异步处理的功能方法
2016/12/10 PHP
JavaScript 题型问答有答案参考
2010/02/17 Javascript
javascript中字符串替换函数replace()方法与c# 、vb 替换有一点不同
2010/06/25 Javascript
SwfUpload在IE10上不出现上传按钮的解决方法
2013/06/25 Javascript
解析JavaScript中点号“.”的多义性
2013/12/02 Javascript
javascript实现的固定位置悬浮窗口实例
2015/04/30 Javascript
jquery+php实现滚动的数字特效
2015/11/29 Javascript
JavaScript 函数的执行过程
2016/05/09 Javascript
AngularJS过滤器filter用法实例分析
2016/11/04 Javascript
jquery封装插件时匿名函数形参和实参的写法解释
2017/02/14 Javascript
JS设置手机验证码60s等待实现代码
2017/06/14 Javascript
Angular2开发环境搭建教程之VS Code
2017/12/15 Javascript
axios拦截设置和错误处理方法
2018/03/05 Javascript
利用js将ajax获取到的后台数据动态加载至网页中的方法
2018/08/08 Javascript
javascript将非数值转换为数值
2018/09/13 Javascript
[42:23]完美世界DOTA2联赛PWL S3 Forest vs Rebirth 第二场 12.10
2020/12/13 DOTA
Python Web框架Tornado运行和部署
2020/10/19 Python
zookeeper python接口实例详解
2018/01/18 Python
numpy实现合并多维矩阵、list的扩展方法
2018/05/08 Python
python基础学习之如何对元组各个元素进行命名详解
2018/07/12 Python
django 模版关闭转义方式
2020/05/14 Python
python Matplotlib基础--如何添加文本和标注
2021/01/26 Python
css3 transform导致子元素固定定位变成绝对定位的方法
2020/03/06 HTML / CSS
HTML5、Select下拉框右边加图标的实现代码(增进用户体验)
2017/10/16 HTML / CSS
理肤泉英国官网:La Roche-Posay英国
2019/01/14 全球购物
学校经典推荐信
2013/10/30 职场文书
会计毕业生自荐信
2013/11/21 职场文书
班级入场式解说词
2014/02/01 职场文书
语文课外活动总结
2014/08/27 职场文书
六五普法宣传标语
2014/10/06 职场文书
2014年污水处理厂工作总结
2014/12/19 职场文书
介绍信怎么写
2015/01/30 职场文书
倡议书的格式写法
2015/04/28 职场文书
乡镇科协工作总结2015
2015/05/19 职场文书
毕业论文答辩开场白和结束语
2015/05/27 职场文书