【Node事件模块Events】

来源:互联网 发布:苹果淘宝直播怎么加入 编辑:程序博客网 时间:2024/05/18 04:48

环境:Node v8.2.1; Npm v5.3.0; OS Windows10

1、 Node事件介绍


Node大多数核心 API 都采用惯用的异步事件驱动架构,其中某些类型的对象(触发器)会周期性地触发命名事件来调用函数对象(监听器)。

所有能触发事件的对象都是 EventEmitter 类的实例。 这些对象开放了一个 eventEmitter.on() 函数,允许将一个或多个函数绑定到会被对象触发的命名事件上。 事件名称通常是驼峰式的字符串,但也可以使用任何有效的 JavaScript 属性名。

当 EventEmitter 对象触发一个事件时,所有绑定在该事件上的函数都被同步地调用。 监听器的返回值会被丢弃。

2、events 模块API介绍


这里写图片描述

3、 一些例子


下面是一些简单的例子,对应上面的API的一个代码实现

3.1 绑定和触发事件


const EventEmitter = require('events');//自定义一个对象继承于EventEmitterclass MyEmitter extends EventEmitter { }const myEmitter = new MyEmitter();myEmitter.on('event', () => {  console.log('触发了一个事件!');});myEmitter.emit('event');

3.2 为事件传递参数


const EventEmitter = require('events');class MyEmitter extends EventEmitter {}const myEmitter = new MyEmitter();myEmitter.on('event', (a,b) => { console.log(a,b); //1,2}); myEmitter.emit('event','a','b');

3.3 this 的问题


当一个普通的监听器函数被 EventEmitter 调用时,标准的 this 关键词会被设置指向监听器所附加的 EventEmitter。

const EventEmitter = require('events');class MyEmitter extends EventEmitter {}const myEmitter = new MyEmitter();myEmitter.on('event', function() {    console.log(this);    /*        a b MyEmitter {            domain: null,            _events: { event: [Function] },            _eventsCount: 1,            _maxListeners: undefined         }    */   }); myEmitter.emit('event');

也可以使用 ES6 的箭头函数作为监听器。但是这样 this 关键词就不再指向 EventEmitter 实例:

const EventEmitter = require('events');class MyEmitter extends EventEmitter {}const myEmitter = new MyEmitter();myEmitter.on('event', () => {    console.log(this);    //{}}); myEmitter.emit('event');

3.4 异步执行


EventListener 会按照监听器注册的顺序同步地调用所有监听器,监听器函数可以使用 setImmediate() 或 process.nextTick() 方法切换到异步操作模式:

const EventEmitter = require('events');class MyEmitter extends EventEmitter {}const myEmitter = new MyEmitter();myEmitter.on('event', (a,b) => {    setImmediate(()=>{        //异步触发        console.log(a,b);    })    console.log("c");}); myEmitter.emit('event','a','b');//c//a b

3.5 无限次触发和一次触发


事件默认是可以无限次数的触发的,只要触发一次,对应的监听函数就执行一次;有时候我们希望只执行一次监听函数,可以使用【once】对事件进行绑定

多次触发:

const EventEmitter = require('events')class MyEmitter extends EventEmitter { }const myEmitter = new MyEmitter();let m = 0;myEmitter.on('event', () => {    console.log(++m);});myEmitter.emit('event');    //1myEmitter.emit('event');    //2myEmitter.emit('event');    //3

一次触发:

const EventEmitter = require('events')class MyEmitter extends EventEmitter { }const myEmitter = new MyEmitter();let m = 0;myEmitter.once('event', () => {    console.log(++m);});myEmitter.emit('event');    //1myEmitter.emit('event');    //忽略myEmitter.emit('event');    //忽略

3.6 错误事件


当 EventEmitter 实例中发生错误时,会触发一个 ‘error’ 事件,如果 EventEmitter 没有为 ‘error’ 事件注册至少一个监听器,则当 ‘error’ 事件触发时,会抛出错误、打印堆栈跟踪、且退出 Node.js 进程。

const EventEmitter = require('events');class MyEmitter extends EventEmitter { }const myEmitter = new MyEmitter();myEmitter.emit("error", new Error('whoops!'));// 抛出错误,并使 Node.js 崩溃

为了防止 Node.js 进程崩溃,可以在 process 对象的 uncaughtException 事件上注册监听器

const EventEmitter = require('events')class MyEmitter extends EventEmitter { }const myEmitter = new MyEmitter();//在进程上面注册错误监听,使进程不崩溃process.on("uncaughtException",()=>{    console.error('有错误');});myEmitter.emit("error",new Error("whoops"))

上面这样的方式并不是最佳实践,最好是为【error】注册监听函数

3.7 获取和修改最大事件监听数量


Node默认一个事件的监听数量为10个,超过十个将会发出警告

const EventEmitter = require('events')class MyEmitter extends EventEmitter { }const myEmitter = new MyEmitter();console.log(EventEmitter.defaultMaxListeners);    //10for (let i = 0; i < 11; i++) {    myEmitter.on("event", () => {        console.log(i);    });}myEmitter.emit("event")//MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 event listeners added. Use emitter.setMaxListeners() to increase limit

改变指定的 EventEmitter 实例的监听器限制

const EventEmitter = require('events')class MyEmitter extends EventEmitter { }const myEmitter = new MyEmitter();myEmitter.setMaxListeners(13);for (let i = 0; i < 11; i++) {    myEmitter.on("event", () => {        console.log(i);    });}myEmitter.emit("event")

3.8 newListener事件


EventEmitter 实例会在一个监听器被添加到其内部监听器数组【之前】触发自身的 ‘newListener’ 事件

const EventEmitter = require('events')class MyEmitter extends EventEmitter { }const myEmitter = new MyEmitter()myEmitter.once("newListener", (event, listener) => {    if(event === "event"){        myEmitter.on("event",()=>{            console.log("B");        })    }});myEmitter.on("event",()=>{    console.log("A");});myEmitter.emit("event")/*BA*/

segmentfault【Node事件模块Events】同步更新