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 相关文章推荐
web 页面分页打印的实现
Jun 22 Javascript
JQuery中根据属性或属性值获得元素(6种情况获取方法)
Jan 17 Javascript
jquery each的几种常用的使用方法示例
Jan 21 Javascript
javascript查询字符串参数的方法
Jan 28 Javascript
自定义百度分享的分享按钮
Mar 18 Javascript
jquery任意位置浮动固定层插件用法实例
May 29 Javascript
javascript中Array()数组函数详解
Aug 23 Javascript
Vue中实现权限控制的方法示例
Jun 07 Javascript
tweenjs缓动算法的使用实例分析
Aug 26 Javascript
微信小程序点击列表跳转到对应详情页过程解析
Sep 26 Javascript
详解如何在vue+element-ui的项目中封装dialog组件
Dec 11 Vue.js
Vue3.0写自定义指令的简单步骤记录
Jun 27 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
如何去掉文章里的 html 语法
2006/10/09 PHP
PHP has encountered an Access Violation at 7C94BD02解决方法
2009/08/24 PHP
常用的PHP数据库操作方法(MYSQL版)
2011/06/08 PHP
php从文件夹随机读取文件的方法
2015/06/01 PHP
PHP实现的mysql主从数据库状态检测功能示例
2017/07/20 PHP
javascript实现的基于金山词霸网络翻译的代码
2010/01/15 Javascript
将两个div左右并列显示并实现点击标题切换内容
2013/10/22 Javascript
jQuery分别获取选中的复选框值的示例
2014/06/17 Javascript
jquery实现点击弹出带标题栏的弹出层(从右上角飞入)效果
2015/09/19 Javascript
AngularJS实现星星等级评分功能
2016/09/24 Javascript
JS控制页面跳转时未请求要跳转的地址怎么回事
2016/10/14 Javascript
JS实现复选框的全选和批量删除功能
2017/04/05 Javascript
jquery实现回车键触发事件(实例讲解)
2017/11/21 jQuery
jQuery.parseJSON()函数详解
2019/02/28 jQuery
JS如何把字符串转换成json
2020/02/21 Javascript
vue项目中使用vue-layer弹框插件的方法
2020/03/11 Javascript
vue利用全局导航守卫作登录后跳转到未登录前指定页面的实例代码
2020/05/19 Javascript
Vue中key的作用示例代码详解
2020/06/10 Javascript
[03:04]2018年国际邀请赛典藏宝瓶&莱恩声望物品展示 片尾有彩蛋
2018/06/04 DOTA
解析Python中的二进制位运算符
2015/05/13 Python
利用python和百度地图API实现数据地图标注的方法
2019/05/13 Python
Python collections中的双向队列deque简单介绍详解
2019/11/04 Python
pytorch: Parameter 的数据结构实例
2019/12/31 Python
python2 对excel表格操作完整示例
2020/02/23 Python
Python3爬虫中pyspider的安装步骤
2020/07/29 Python
css3动画事件—webkitAnimationEnd与计时器time事件
2013/01/31 HTML / CSS
HTML5 语音搜索只需一句代码
2013/01/03 HTML / CSS
HTML5拖拉上传文件的简单实例
2017/01/11 HTML / CSS
柒牌官方商城:中国男装优秀品牌
2017/06/30 全球购物
运输服务质量承诺书
2014/03/27 职场文书
《真想变成大大的荷叶》教学反思
2014/04/14 职场文书
统计专业自荐书
2014/07/06 职场文书
干部年终考核评语
2015/01/04 职场文书
被委托人身份证明
2015/08/07 职场文书
互联网创业商业模式以及赚钱法则有哪些?
2019/10/12 职场文书
祝福语集锦:朋友新店开业祝福语
2019/12/10 职场文书