资讯专栏INFORMATION COLUMN

【Node事件模块Events】

junnplus / 661人阅读

环境: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");

//自定义一个对象继承于EventEmitter
class 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");    //1

myEmitter.emit("event");    //2

myEmitter.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");    //1

myEmitter.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);    //10

for (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")
/*
B
A
*/

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

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/88738.html

相关文章

  • 深入nodejs-核心模块Events详解(事件驱动)

    摘要:实现方式其实就是对方法做了一层封装,将一个封装好的代替传递给方法内部会执行一次监听回调函数,然后再调用对该回调进行删除。 事件驱动 Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。Node.js 使用了一个事件驱动、非阻塞式 I/O的模型,使其轻量又高效。Allows you to build scalable network applicati...

    hidogs 评论0 收藏0
  • Node 之 Event 模块

    摘要:为什么把叫做集合而不能称为严格意义上的对象,来看这个集合的构造函数可以见得,是与处于同一层级的而非是继承自,所以说由实例出来的对象更加的纯净,并没有诸如等方法,更像是一个集合。 写在前面 事件的编程方式具有轻量级、松耦合、只关注事务点等优势,在浏览器端,有着自己的一套DOM事件机制,其中含包括这诸如事件冒泡,事件捕获等;然而Node的事件机制没有事件冒泡等,其原理就是设计模式中的观察者...

    mrli2016 评论0 收藏0
  • Node.js知识点详解(二)HTTP模块事件模块

    摘要:如果不能快速返回,就应当将其迁移到另一个进程中模块让开发人员可以为事件设置侦听器和处理器。我们需要给每个想要响应的事件创建侦听器 Node.js的http服务器 通过使用HTTP模块的低级API,Node.js允许我们创建服务器和客户端。刚开始学node的时候,我们都会遇到如下代码: var http = require(http); http.createServer(funct...

    Lionad-Morotar 评论0 收藏0
  • Node事件机制小记

    摘要:事件的监听与事件的触发事件一事件机制的实现中大部分的模块,都继承自模块。从另一个角度来看,事件侦听器模式也是一种事件钩子的机制,利用事件钩子导出内部数据或状态给外部调用者。的核心就是事件发射与事件监听器功能的封装。 nodejs事件的监听与事件的触发 nodejs事件(Events)showImg(https://segmentfault.com/img/bV0Sqi?w=692&h=...

    airborne007 评论0 收藏0
  • EventEmitter的实现

    摘要:实例方法的话,最核心的就是分别是添加事件,删除事件,发布事件。为了防止进程崩溃,可以在对象的事件上注册监听器,或使用模块。注意,模块已被废弃。作为最佳实践,应该始终为事件注册监听器。 前言 事件在js中非常的常见,不管是浏览器还是node,这种事件发布/订阅模式的应用都是很常见的。至于发布/订阅模式和观察者模式是否是同一种设计模式说法都有,这里不做具体的讨论。在之前的项目中也曾自己实现...

    CoreDump 评论0 收藏0

发表评论

0条评论

junnplus

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<