Node中的事件循环
事件循环是Node的核心,正是因为有了事件循环JS才能够在服务端占有一席之地。JS是一种单线程语言,但是它的执行环境是多线程的在加上JS的事件驱动这一特点,使使JS在执行的过程中没执行到一个异步操作就交由后台处理然后继续向下执行,在遇上一个异步操作又交由后台处理,JS的执行线程不会发生阻塞,一旦JS代码执行完毕就会去后台查看有没有满足条件的异步操作一旦有满足条件的就执行事先定义好的处理函数。
在Node中通过EventEmitter(事件发生器)来实现这种功能,EventEmitter和我们在浏览器中使用自定义事件的方式是差不多的,其使用方式为:
var events = require("events").EventEmitter; var event = new events; event.on("zt",function(){console.log(111)}); event.emit("zt");
通过require("events").EventEmitter来获取事件发生器函数,我们在实例化一个对象,这样这个对象就获得了事件发生器原型上的方法,分别为on和emit,我们可以通过on()函数来注册一个事件,它可以接收两个参数第一个参数为eventName,第二个参数为对应的事件处理函数。在绑定事件之后可以通过emit来主动触发事件。
事件发生器可以为一个事件绑定多个事件处理函数,并且它的执行顺序是可以保证的,在前面的优先执行:
var events = require("events").EventEmitter; var event = new events; event.on("zt",function(){console.log("我是第一个处理函数")}); event.on("zt",function(){console.log("我是第二个处理函数")}); event.emit("zt");
事件处理函数同样可以接收参数,在主动触发时传入参数即可:
var events = require("events").EventEmitter; var event = new events; event.on("zt",function(a,b){console.log("我是第一个处理函数"+"参数1:"+a+"参数2:"+b)}); event.on("zt",function(a){console.log("我是第二个处理函数"+"参数1:"+a)}); event.emit("zt","AA","BB");
在使用emit()时第一个参数表示要触发的事件,后面的参数就表示事件处理函数的参数。
事件发生器可以实现异步,但其本身是同步的:
var events = require("events").EventEmitter; var event = new events; event.on("zt",function(){console.log("我是第一个处理函数")}); event.on("zt",function(){console.log("我是第二个处理函数")}); setTimeout(function(){ event.emit("zt"); },1000); event.on("zt",function(){console.log("我是第三个处理函数")});
事件发生器的on方法等价于一个存储方法,它会把事件名和事件处理函数存储起来,并不会执行,一旦使用emit触发事件之后执行已经存储的处理函数,在emit触发事件后已经添加的事件处理函数就会立即执行,这个操作并不是异步的。
var events = require("events").EventEmitter; var event = new events; event.on("zt",function(){console.log("我是第一个处理函数")}); event.on("zt",function(){console.log("我是第二个处理函数")}); event.emit("zt"); event.on("zt",function(){console.log("我是第三个处理函数")});
将上面的定时器去掉,如果emit是一个异步操作那么第三个处理函数就会执行,但是事实上程序只是执行了前两个事件处理函数。