当前位置: 首页 > 后端技术 > Node.js

Node事件机制笔记

时间:2023-04-03 20:06:20 Node.js

nodejs事件监听与事件触发nodejs事件(Events)一、事件机制的实现Node.js中的大部分模块都是继承自Event模块(http://nodejs.org/docs/最新的...)。事件模块(events.EventEmitter)是事件侦听器模式的简单实现。具有addListener/on、once、removeListener、removeAllListeners、emit等基本事件监听方式的方法实现,与前端DOM树上的事件不一样,因为它没有冒泡等DOM事件行为和逐层捕获,并没有preventDefault()、stopPropagation()、stopImmediatePropagation()等处理事件传递的方法。从另一个角度来看,事件监听器模式也是一种事件钩子的机制,它使用事件钩子将内部数据或状态导出给外部调用者。Node.js中的大部分对象都具有黑盒和功能点少的特点。如果没有事件钩子的形式,我们就无法获得对象运行过程中的中间值或内部状态。这种hook事件的方式可以让程序员不用关注组件是如何启动和执行的,而只关注需要的事件点。2.事件触发events模块只提供了一个对象:events.EventEmitter。EventEmitter的核心是对事件发射和事件监听函数的封装。EventEmitter的每个事件都由一个事件名称和几个参数组成。事件名称是一个字符串,通常表达一定的语义。对于每个事件,EventEmitter支持多个事件侦听器。当一个事件发出时,依次调用注册到该事件的事件监听器,并将事件参数作为回调函数参数传递。  下面用例子来解释这个过程://引入事件模块varevents=require("events");//创建事件监听的对象varemitter=newevents.EventEmitter();//监听eventssome_eventemmitter.addListener("some_event",function(){console.log("事件触发,调用这个回调函数");});//触发事件some_eventemitter.emit("some_event"); 运行结果:eventTrigger,调用这个回调函数 例子:varevents=require('events');varemitter=newevents.EventEmitter();emitter.on('someEvent',function(arg1,arg2){console.log('listener1',arg1,arg2);});emitter.on('someEvent',function(arg1,arg2){console.log('listener2',arg1,arg2);});emitter.emit('someEvent','byvoid',1991); 运行结果为:  listener1byvoid1991listener2byvoid1991  在上面的例子中,发射器为事件someEvent注册了两个事件监听器,然后发射someEvent事件。在运行结果中,可以看到先后调用了两个事件监听回调函数。这是EventEmitter最简单的用法。接下来介绍一下EventEmitter常用的API。  EventEmitter.on(event,listener)为指定事件注册一个监听器,接受一个字符串事件和一个回调函数监听器。EventEmitter.emit(event,[arg1],[arg2],[...])发出事件事件,将一些可选参数传递给事件侦听器的参数表。  EventEmitter.once(event,listener)为指定事件注册一个一次性的监听器,即监听器最多只会被触发一次,触发后立即释放监听器。  EventEmitter.removeListener(event,listener)移除一个指定事件的监听器,该监听器必须是该事件的注册监听器。  EventEmitter.removeAllListeners([event])移除所有事件的所有监听器,如果指定了event,则移除指定事件的所有监听器。  更详细的API文档见http://nodejs.org/api/events.... 想想其实和jquery自定义事件很像//Bindhelloeventtoelementelement.on("hello",function(){alert("helloworld!");});//触发hello事件element.trigger("hello");3、事件机制的高级应用继承event.EventEmitter实现一个继承EventEmitter的类是非常简单的。下面是Node.js中流对象继承EventEmitter的例子:varutil=require("util");varevents=require("events");//创建构造函数Stream(){call(this);}util.inherits(Stream,events.EventEmitter);//实例创建事件监听对象varelem=newStream();//监听事件elem.addListener("one_event",function(){console.log("事件触发,调用此回调函数");});//触发事件some_eventelem.emit("one_event");值得一提的是,如果你给一个事件添加超过10个监听器,你会得到一个警告,这个设计是为了在单线程中运行与Node.js本身有关,设计者认为监听器过多可能会导致内存泄漏,所以才会有这样的警告。示例:varutil=require("util");varevents=require("events");functionStream(){events.EventEmitter.call(this);}util.inherits(Stream,events.EventEmitter);varelem=newStream();elem.addListener("我在这里",function(arg1,arg2){console.log("事件触发,调用此回调函数",arg1,arg2,1);});elem.addListener("我来了",function(arg1,arg2){console.log("事件触发,调用此回调函数",arg1,arg2,2);});elem.addListener("我来了",function(arg1,arg2){console.log("事件触发,调用这个回调函数",arg1,arg2,3);});elem.addListener("我来了",function(arg1,arg2){console.log("事件触发,调用此回调函数",arg1,arg2,4);});elem.addListener("我在这儿",function(arg1,arg2){console.log("事件触发,调用这个回调函数",arg1,arg2,5);});elem.addListener("我在here",function(arg1,arg2){console.log("事件触发,调用此回调函数",arg1,arg2,6);});elem.addListener("我来了",function(arg1,arg2){console.log("事件触发,调用此回调函数",arg1,arg2,7);});elem.addListener("我来了",function(arg1,arg2){console.log("event触发,调用这个回调函数",arg1,arg2,8);});elem.addListener("我来了",function(arg1,arg2){console.log("事件触发,调用此回调函数",arg1,arg2,9);});elem.addListener("我在这儿",function(arg1,arg2){console.log("事件触发,调用这个回调函数",arg1,arg2,10);});elem.addListener("我在here",function(arg1,arg2){console.log("事件触发,调用此回调函数",arg1,arg2,11);});//触发事件some_eventelem.emit("我来了",'一二');我们可以通过调用emitter.setMaxListeners(0)来限制emitter.setMaxListeners(0);一个经典的事件监听触发器,进程通信示例:master.js varchildprocess=require('child_process');varworker=childprocess.fork('./worker.js');console.log('pidinmaster:',process.pid);//监听事件worker.on('message',function(msg){console.log('1:',msg);})process.on('message',function(msg){console.log('2:',msg);})worker.send('---');//触发事件messageprocess.emit('message','------');  worker.jsconsole.log('pidinworker:',process.pid);process.on('message',function(msg){console.log('3:',msg);});process.send('===');process.emit('message','=======');  运行结果:$nodemaster.jspidinmaster:22229//主进程创建后打印pid2:------//主进程收到发给自己的消息pidinworker:22230//子进程创建后,打印其pid3:======//子进程收到发给自己的消息1:===//主进程收到来自子进程的消息3:---//子进程收到来自主进程的消息。有两个有意思的地方:  在主进程中,使用worker.on('message',...)监听子进程的消息,使用process.on('message',...)监听消息发给自己但在子进程中,只有process.on('message',...)是消息监听方式,无法区分消息来源。如果出现给自己发消息的情况,必须在消息发送代码前加上相应的消息监听代码,否则无法监听消息发送。例如,如果您将最后一行代码放在process.emit('message','------');在master.js文件的第一行写入,运行结果不会输出2:------。如果无法控制消息监听代码和消息发送代码的顺序,可以将给自己发送消息的代码重写为setImmediate(process.emit.bind(process,'message',{{message}}));   参考资料:  http://www.cnblogs.com/zhongw...(例子很多)  http://www.infoq.com/cn/artic...  http://www.toolmao.com/nodejs...  http://www.ynpxrz.com/n691854...  http://www.jb51.net/article/6...