当前位置: 首页>NodeJS>Node.js的事件机制

Node.js的事件机制

时间:2015-07-02 09:28 来源:网络整理 作者:KKWL 点击:
Node.js的事件机制 原文地址: Node.js在其Github代码仓库(https://github.com/joyent/node)上有着一句短短的介绍:Evented I/O for V8 JavaScript。这句近似广告语的句子却道尽了Node.js自身的特色所在:

 

Node.js的事件机制

 原文地址:   

 Node.js在其Github代码仓库(https://github.com/joyent/node)上有着一句短短的介绍:Evented I/O for V8 JavaScript。这句近似广告语的句子却道尽了Node.js自身的特色所在:基于V8引擎实现的事件驱动IO。

    Node.js能够在众多的后端JavaScript技术之中脱颖而出,正是因其基于事件的特点而受到欢迎。拿Rhino来做比较,可以看出Rhino引擎支持的后端JavaScript摆脱不掉其他语言同步执行的影响,导致JavaScript在后端编程与前端编程之间有着十分显著的差别,在编程模型上无法形成统一。在前端编程中,事件的应用十分广泛,DOM上的各种事件。在Ajax大规模应用之后,异步请求更得到广泛的认同,而Ajax亦是基于事件机制的。在Rhino中,文件读取等操作,均是同步操作进行的。在这类单线程的编程模型下,如果采用同步机制,无法与PHP之类的服务端脚本语言的成熟度媲美,性能也没有值得可圈可点的部分。直到Ryan Dahl在2009年推出Node.js后,后端JavaScript才走出其迷局。Node.js的推出,我觉得该变了两个状况:
  (1)统一了前后端JavaScript的编程模型。


    Node.js能够在众多的后端JavaScript技术之中脱颖而出,正是因其基于事件的特点而受到欢迎。拿Rhino来做比较,可以看出Rhino引擎支持的后端JavaScript摆脱不掉其他语言同步执行的影响,导致JavaScript在后端编程与前端编程之间有着十分显著的差别,在编程模型上无法形成统一。在前端编程中,事件的应用十分广泛,DOM上的各种事件。在Ajax大规模应用之后,异步请求更得到广泛的认同,而Ajax亦是基于事件机制的。在Rhino中,文件读取等操作,均是同步操作进行的。在这类单线程的编程模型下,如果采用同步机制,无法与PHP之类的服务端脚本语言的成熟度媲美,性能也没有值得可圈可点的部分。直到Ryan Dahl在2009年推出Node.js后,后端JavaScript才走出其迷局。Node.js的推出,我觉得该变了两个状况:
  (1)统一了前后端JavaScript的编程模型。

  (2)利用事件机制充分利用用异步IO突破单线程编程模型的性能瓶颈,使得JavaScript在后端达到实用价值。

 

  有了第二次浏览器大战中的佼佼者V8的适时助力,使得Node.js在短短的两年内达到可观的运行效率,并迅速被大家接受。这一点从Node.js项目在Github上的流行度和NPM上的库的数量可见一斑。

   至于Node.js为何会选择Evented I/O for V8 JavaScript的结构和形式来实现,可以参见一下2011年初对作者Ryan Dahl的一次采访: 。


1  事件机制的实现



   Node.js中大部分的模块,都继承自Event模块( )。

   Event模块(events.EventEmitter)是一个简单的事件监听器模式的实现。具有addListener/on,once,removeListener,removeAllListeners,emit等基本的事件监听模式的方法实现。它与前端DOM树上的事件并不相同,因为它不存在冒泡,逐层捕获等属于DOM的事件行为,也没有preventDefault()、stopPropagation()、 stopImmediatePropagation() 等处理事件传递的方法。



   从另一个角度来看,事件侦听器模式也是一种事件钩子(hook)的机制,利用事件钩子导出内部数据或状态给外部调用者。Node.js中的很多对象,大多具有黑盒的特点,功能点较少,如果不通过事件钩子的形式,对象运行期间的中间值或内部状态,是我们无法获取到的。这种通过事件钩子的方式,可以使编程者不用关注组件是如何启动和执行的,只需关注在需要的事件点上即可。


 

var options = { host: 'www.google.com', port: 80, path: '/upload', method: 'POST' }; var req = http.request(options, function (res) { console.log('STATUS: ' + res.statusCode); console.log('HEADERS: ' + JSON.stringify(res.headers)); res.setEncoding('utf8'); res.on('data', function (chunk) { console.log('BODY: ' + chunk); }); }); req.on('error', function (e) { console.log('problem with request: ' + e.message); }); // write data to request body req.write('data\n'); req.write('data\n'); req.end();
在这段HTTP request的代码中,程序员只需要将视线放在error,data这些业务事件点即可,至于内部的流程如何,无需过于关注。

  值得一提的是如果对一个事件添加了超过10个侦听器,将会得到一条警告,这一处设计与Node.js自身单线程运行有关,设计者认为侦听器太多,可能导致内存泄漏,所以存在这样一个警告。调用:

 

emitter.setMaxListeners(0);

 

顶一下
(0)
0%
踩一下
(0)
0%
------分隔线----------------------------