资讯专栏INFORMATION COLUMN

【每日一包0025】events

shixinzhang / 2480人阅读

摘要:打印的参数分别为移除的监听事件和该事件的句柄函数默认情况下,每个事件可以注册最多个监听器。返回已注册监听器的事件名数组。值设为或表示不限制监听器的数量。持续地记录返回一个数组,只包含绑定的监听器。

[github地址:https://github.com/ABCDdouyae...]

events

</>复制代码

  1. 事件触发器
大多数 Node.js 核心 API 构建于惯用的异步事件驱动架构,其中某些类型的对象(又称触发器,Emitter)会触发命名事件来调用函数(又称监听器,Listener)。所有能触发事件的对象都是 EventEmitter 类的实例。 这些对象有一个 eventEmitter.on() 函数,用于将一个或多个函数绑定到命名事件上。 事件的命名通常是驼峰式的字符串。当 EventEmitter 对象触发一个事件时,所有绑定在该事件上的函数都会被同步地调用

基本用法:实例化一个监听器,注册监听事件‘event’,当通过emit触发‘event’时候,会调用回调函数

</>复制代码

  1. const EventEmitter = require("events");
  2. class MyEmitter extends EventEmitter{}
  3. const myEmitter = new MyEmitter();
  4. myEmitter.on("event", ()=>{
  5. console.log("触发事件")
  6. });
  7. myEmitter.emit("event");
eventEmitter.emit() 方法可以传任意数量的参数到监听器函数。 当监听器函数被调用时,this 关键词会被指向监听器所绑定的 EventEmitter 实例。

</>复制代码

  1. myEmitter.on("event1", function(a ,b){
  2. console.log(a, b, this)//1 2 MyEmitter{}
  3. });
  4. myEmitter.emit("event1", 1, 2);

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

</>复制代码

  1. myEmitter.on("event", (a, b) => {
  2. console.log(a, b, this);
  3. // 打印: a b {}
  4. });
  5. myEmitter.emit("event", "a", "b");
使用 eventEmitter.once() 可以注册最多可调用一次的监听器。 当事件被触发时,监听器会被注销,然后再调用。

</>复制代码

  1. let m = 0;
  2. myEmitter.once("event", () => {
  3. console.log(++m);
  4. });
  5. myEmitter.emit("event");
  6. // 打印: 1
  7. myEmitter.emit("event");
  8. // 不触发
当 EventEmitter 实例出错时,应该触发 "error" 事件。如果没有为 "error" 事件注册监听器,则当 "error" 事件触发时,会抛出错误、打印堆栈跟踪、并退出 Node.js 进程

</>复制代码

  1. myEmitter.emit("error", new Error("错误信息"));
  2. // 抛出错误

作为最佳实践,应该始终为 "error" 事件注册监听器。

</>复制代码

  1. myEmitter.on("error", (err) => {
  2. console.error("错误信息");
  3. });
  4. myEmitter.emit("error", new Error("错误信息"));
  5. // 打印: 错误信息
EventEmitter 类由 events 模块定义:

</>复制代码

  1. const EventEmitter = require("events");

当新增监听器时,会触发 "newListener" 事件;当移除已存在的监听器时,则触发 "removeListener" 事件。

newListener的参数分别为增加的监听事件和该事件的句柄函数

</>复制代码

  1. myEmitter.once("newListener", (event, listener)=>{
  2. console.log(event, listener)// "event1" fn
  3. });
  4. function fn(){
  5. console.log(1)
  6. }
  7. myEmitter.on("event1", fn)

在添加监听器之前触发 "newListener" 事件有一个副作用: 如果在回调中注册同名事件的监听器,则该监听器会被插入到正被添加的监听器前面。

</>复制代码

  1. const myEmitter = new MyEmitter();
  2. // 只处理一次,避免无限循环。
  3. myEmitter.once("newListener", (event, listener) => {
  4. if (event === "event") {
  5. // 在前面插入一个新的监听器。
  6. myEmitter.on("event", () => {
  7. console.log("B");
  8. });
  9. }
  10. });
  11. myEmitter.on("event", () => {
  12. console.log("A");
  13. });
  14. myEmitter.emit("event");
  15. // 打印:
  16. // B
  17. // A

removeListener的参数分别为移除的监听事件和该事件的句柄函数

EventEmitter.defaultMaxListeners默认情况下,每个事件可以注册最多 10 个监听器。 可以使用 emitter.setMaxListeners(n) 方法改变单个 EventEmitter 实例的限制。 可以使用 EventEmitter.defaultMaxListeners 属性改变所有 EventEmitter 实例的默认值。设置 EventEmitter.defaultMaxListeners 要谨慎,因为会影响所有 EventEmitter 实例,包括之前创建的。 因而,优先使用 emitter.setMaxListeners(n) 而不是 `EventEmitter.defaultMaxListeners。限制不是硬性的。 EventEmitter 实例可以添加超过限制的监听器,但会向 stderr 输出跟踪警告,表明检测到可能的内存泄漏。 对于单个 EventEmitter 实例,可以使用 emitter.getMaxListeners()emitter.setMaxListeners() 暂时地消除警告

</>复制代码

  1. console.log(myEmitter.getMaxListeners())//10
  2. myEmitter.setMaxListeners(11);
  3. function fn(){
  4. console.log(1)//11个1
  5. }
  6. for(var i=0;i<11;i++){
  7. myEmitter.on("event1", fn)
  8. }
  9. myEmitter.emit("event1")
emitter.addListener(eventName, listener), emitter.on(eventName, listener)的别名 emitter.emit(eventName[, ...args])按照监听器注册的顺序,同步地调用每个注册到名为 eventName 的事件的监听器,并传入提供的参数。如果事件有监听器,则返回 true,否则返回 false。 emitter.eventNames() 返回已注册监听器的事件名数组。 数组中的值为字符串或 `Symbol。

</>复制代码

  1. const EventEmitter = require("events");
  2. const myEE = new EventEmitter();
  3. myEE.on("foo", () => {});
  4. myEE.on("bar", () => {});
  5. const sym = Symbol("symbol");
  6. myEE.on(sym, () => {});
  7. console.log(myEE.eventNames());
  8. // 打印: [ "foo", "bar", Symbol(symbol) ]
emitter.getMaxListeners()返回 EventEmitter 当前的监听器最大限制数的值 emitter.listenerCount(eventName)返回正在监听的名为 eventName 的事件的监听器的数量。 emitter.listeners(eventName)返回名为 eventName 的事件的监听器数组的副本。

</>复制代码

  1. let fn1 = ()=>{}, fn2 = ()=>{};
  2. myEmitter.on("foo", fn1);
  3. myEmitter.on("foo", fn2);
  4. console.log(myEmitter.listeners("foo"));
  5. //[ [Function: fn1], [Function: fn2] ]
emitter.off(eventName, listener), emitter.removeListener() 的别名。 emitter.prependListener(eventName, listener)添加 listener 函数到名为 eventName 的事件的监听器数组的开头。 不会检查 listener 是否已被添加。 多次调用并传入相同的 eventName 和 listener 会导致 listener 被添加多次。 emitter.prependOnceListener(eventName, listener)添加单次监听器 listener 到名为 eventName 的事件的监听器数组的开头。 当 eventName 事件下次触发时,监听器会先被移除,然后再调用。 emitter.removeAllListeners([eventName])移除全部监听器或指定的 eventName 事件的监听器。 emitter.removeListener(eventName, listener)从名为 eventName 的事件的监听器数组中移除指定的 listener。

</>复制代码

  1. let fn1 = ()=>{console.log(1)}, fn2 = ()=>{console.log(2)};//2
  2. myEmitter.on("foo", fn1);
  3. myEmitter.on("foo", fn2);
  4. console.log(myEmitter.listeners("foo"));
  5. //[ [Function: fn1], [Function: fn2] ]
  6. myEmitter.off("foo", fn1);
  7. myEmitter.emit("foo");
emitter.setMaxListeners(n)默认情况下,如果为特定事件添加了超过 10 个监听器,则 EventEmitter 会打印一个警告。 这有助于发现内存泄露。 但是,并不是所有的事件都要限制 10 个监听器。 emitter.setMaxListeners() 方法可以为指定的 EventEmitter 实例修改限制。 值设为 Infinity(或 0)表示不限制监听器的数量。 emitter.rawListeners(eventName)返回 eventName 事件的监听器数组的拷贝,包括封装的监听器(例如由 .once() 创建的)。

</>复制代码

  1. const emitter = new EventEmitter();
  2. emitter.once("log", () => console.log("只记录一次"));
  3. // 返回一个数组,包含了一个封装了 `listener` 方法的监听器。
  4. const listeners = emitter.rawListeners("log");
  5. const logFnWrapper = listeners[0];
  6. // 打印 “只记录一次”,但不会解绑 `once` 事件。
  7. logFnWrapper.listener();
  8. // 打印 “只记录一次”,且移除监听器。
  9. logFnWrapper();
  10. emitter.on("log", () => console.log("持续地记录"));
  11. // 返回一个数组,只包含 `.on()` 绑定的监听器。
  12. const newListeners = emitter.rawListeners("log");
  13. // 打印两次 “持续地记录”。
  14. newListeners[0]();
  15. emitter.emit("log");

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

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

相关文章

  • 每日一包0025events

    摘要:打印的参数分别为移除的监听事件和该事件的句柄函数默认情况下,每个事件可以注册最多个监听器。返回已注册监听器的事件名数组。值设为或表示不限制监听器的数量。持续地记录返回一个数组,只包含绑定的监听器。 [github地址:https://github.com/ABCDdouyae...] events 事件触发器 大多数 Node.js 核心 API 构建于惯用的异步事件驱动架构,其中某些...

    fxp 评论0 收藏0
  • Python每日一练0025

    摘要:问题如何列举一个目录下的所有文件解决方案使用如果只需要文本文件的话,就结合进行过滤如果对文件有匹配需求的话,比如只需要某个目录的文件,那么可以使用模块,例如讨论会返回一个列表,包含目录下的所有文件,但不会包含和,即使他们是存在的。 问题 如何列举一个目录下的所有文件 解决方案 使用os.listdir() >>> import os >>> os.listdir(.) [.androi...

    Rindia 评论0 收藏0
  • 每日一包0029】merge-descriptors

    摘要:地址源码依赖一个对象的属性继承另一个对象的属性及其属性描述符用法继承者,被继承者是否继承者有该属性的时候继承默认不继承返回继承后的新的对象当第三个参数为时候,原对象又该属性则没有继承被继承者的属性和属性描述符 [github地址:https://github.com/ABCDdouyae...] merge-descriptors (express源码依赖) 一个对象的属性继承另一个对...

    kun_jian 评论0 收藏0
  • 每日一包0029】merge-descriptors

    摘要:地址源码依赖一个对象的属性继承另一个对象的属性及其属性描述符用法继承者,被继承者是否继承者有该属性的时候继承默认不继承返回继承后的新的对象当第三个参数为时候,原对象又该属性则没有继承被继承者的属性和属性描述符 [github地址:https://github.com/ABCDdouyae...] merge-descriptors (express源码依赖) 一个对象的属性继承另一个对...

    printempw 评论0 收藏0

发表评论

0条评论

shixinzhang

|高级讲师

TA的文章

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