node.js学习之事件模块Events的使用示例


Posted in Javascript onSeptember 28, 2017

前言

本文主要给大家介绍了关于node.js事件模块Events使用的一些示例,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧。

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

1、 Node事件介绍

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

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

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

2、events 模块API介绍

node.js学习之事件模块Events的使用示例

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
*/

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
Ajax请求在数据量大的时候出现超时的解决方法
Feb 27 Javascript
JavaScript设计模式学习之“类式继承”
Mar 12 Javascript
JQuery zClip插件实现复制页面内容到剪贴板
Nov 02 Javascript
全面解析Bootstrap表单使用方法(表单控件)
Nov 24 Javascript
完美实现八种js焦点轮播图(上篇)
Jul 18 Javascript
基于js里调用函数时,函数名带括号和不带括号的区别
Jul 28 Javascript
canvas学习之API整理笔记(二)
Dec 29 Javascript
js实现微博发布小功能
Jan 12 Javascript
vue中用H5实现文件上传的方法实例代码
May 27 Javascript
vue.js如何更改默认端口号8080为指定端口的方法
Jul 14 Javascript
详解webpack之scss和postcss-loader的配置
Jan 09 Javascript
vue添加自定义右键菜单的完整实例
Dec 08 Vue.js
es6中的解构赋值、扩展运算符和rest参数使用详解
Sep 28 #Javascript
JS获取日期的方法实例【昨天,今天,明天,前n天,后n天的日期】
Sep 28 #Javascript
jquery实现左右轮播图效果
Sep 28 #jQuery
bootstrap table实现点击翻页功能 可记录上下页选中的行
Sep 28 #Javascript
JavaScript判断输入是否为数字类型的方法总结
Sep 28 #Javascript
详解Node全局变量global模块
Sep 28 #Javascript
React Native预设占位placeholder的使用
Sep 28 #Javascript
You might like
IP138 IP地址查询小偷实现代码
2010/02/15 PHP
PHP类与对象中的private访问控制的疑问
2012/11/01 PHP
浅析php插件 HTMLPurifier HTML解析器
2013/07/01 PHP
memcache命令启动参数中文解释
2014/01/13 PHP
PHP中把对象转换为关联数组代码分享
2015/04/09 PHP
PHP与jquery实时显示网站在线人数实例详解
2016/12/02 PHP
2017年最新PHP经典面试题目汇总(上篇)
2017/03/17 PHP
从javascript语言本身谈项目实战
2006/12/27 Javascript
纯js实现悬浮按钮组件
2016/12/17 Javascript
高效的jQuery代码编写技巧总结
2017/02/22 Javascript
JavaScript函数参数的传递方式详解
2017/03/06 Javascript
prototype.js简单实现ajax功能示例
2017/10/18 Javascript
Windows安装Node.js报错:2503、2502的解决方法
2017/10/25 Javascript
vue axios数据请求及vue中使用axios的方法
2018/09/10 Javascript
浅谈VueJS SSR 后端绘制内存泄漏的相关解决经验
2018/12/20 Javascript
Vue的路由及路由钩子函数的实现
2019/07/02 Javascript
layui将table转化表单显示的方法(即table.render转为表单展示)
2019/09/24 Javascript
使用vscode快速建立vue模板过程详解
2019/10/10 Javascript
nuxt 自定义 auth 中间件实现令牌的持久化操作
2020/11/05 Javascript
Python socket编程实例详解
2015/05/27 Python
python 正确保留多位小数的实例
2018/07/16 Python
Python3实现将一维数组按标准长度分隔为二维数组
2019/11/29 Python
python GUI库图形界面开发之PyQt5滚动条控件QScrollBar详细使用方法与实例
2020/03/06 Python
pycharm 实现光标快速移动到括号外或行尾的操作
2021/02/05 Python
美国网上订购鲜花:FTD
2016/09/23 全球购物
华为c/c++笔试题
2016/01/25 面试题
Linux如何命名文件--使用文件名时应注意
2012/01/22 面试题
外包公司软件测试工程师
2014/11/01 面试题
小学教师国培感言
2014/02/08 职场文书
石油工程专业毕业生求职信
2014/04/13 职场文书
大学新生军训方案
2014/05/03 职场文书
2014年商场国庆节活动策划方案
2014/09/16 职场文书
行政执法队伍作风整顿剖析材料
2014/10/11 职场文书
建筑工程挂靠协议书
2016/03/23 职场文书
为Centos安装指定版本的Docker
2022/04/01 Servers
Win10玩csgo闪退如何解决?Win10玩csgo闪退的解决方法
2022/07/23 数码科技