在nodejs中,事件模块“events”只提供了一个对象“EventEmitter”,它的核心是事件发射与事件监听器。该对象支持若干个事件监听器;当事件发射时,注册到这个事件的事件监听器被依次调用,事件参数作为回调函数参数传递。
本教程操作环境:windows7系统、nodejs 12.19.0版、Dell G3电脑。
nodejs中的事件模块(events)
events是node.js 最重要的模块,events模块只提供了一个对象events.EventEmitter,EventEmitter 的核心是事件发射与事件监听器。
Node.js中大部分的模块,都继承自Event模块。
与DOM树上事件不同,不存在事件冒泡、逐层捕获等行为。
EventEmitter 支持若干个事件监听器。当事件发射时,注册到这个事件的事件监听器被依次调用,事件参数作为回调函数参数传递。
如何访问:
require('events');
emitter.on(event, listener)
/* 调用events模块,获取events.EventEmitter对象 */ var EventEmitter = require('events').EventEmitter; var ee = new EventEmitter(); /* EventEmitter.on(event, listener) 为事件注册一个监听 参数1:event 字符串,事件名 参数2:回调函数 */ ee.on('some_events', function(foo, bar) { console.log("第1个监听事件,参数foo=" + foo + ",bar="+bar ); }); console.log('第一轮'); ee.emit('some_events', 'Wilson', 'Zhong'); console.log('第二轮'); ee.emit('some_events', 'Wilson', 'Z');
emitter.emit(event, [arg1], [arg2], [...])
var EventEmitter = require('events').EventEmitter; var ee = new EventEmitter(); ee.on('some_events', function(foo, bar) { console.log("第1个监听事件,参数foo=" + foo + ",bar="+bar ); });/* EventEmitter.emit(event, [arg1], [arg2], [...]) 触发指定事件 参数1:event 字符串,事件名 参数2:可选参数,按顺序传入回调函数的参数 返回值:该事件是否有监听*/var isSuccess = ee.emit('some_events', 'Wilson', 'Zhong'); ee.on('some_events', function(foo, bar) { console.log("第2个监听事件,参数foo=" + foo + ",bar="+bar ); }); ee.emit('some_events', 'zhong', 'wei');var isSuccess2 = ee.emit('other_events', 'Wilson', 'Zhong'); console.log(isSuccess); console.log(isSuccess2);
示例进行了三次触发事件操作,其中some_events注册了监听,调用时emit函数会返回一个true,而other_events并没有注册监听,emit函数会返回一个false,表示该事件没有监听;当然也可以不用管这个返回值!
emitter.once(event, listener)
var EventEmitter = require('events').EventEmitter; var ee = new EventEmitter();/* EventEmitter.once(event, listener) 为事件注册一次性监听,触发一次后移除监听 参数1:event 字符串,事件名 参数2:回调函数*/ee.once('some_events', function(foo, bar) { console.log("第1个监听事件,参数foo=" + foo + ",bar="+bar ); }); console.log('第一轮'); ee.emit('some_events', 'Wilson', 'Zhong'); console.log('第二轮');var isSuccess = ee.emit('some_events', 'Wilson', 'Zhong'); console.log(isSuccess);
从上面示例代码执行结果可以看出,用emitter.once给some_events注册一个监听后,分两轮调用emitter.emit触发,第二轮会返回false;这表示用emitter.once注册监听和用前面讲的emitter.on注册监听略有不同,
emitter.once注册监听是一次性监听,当触发一次后,会移除该监听!当然,从名字上就看就比较明显了^_^!
emitter.removeListener(event, listener)
先来看一个失败的场景~~~
var EventEmitter = require('events').EventEmitter; var ee = new EventEmitter(); ee.on('some_events', function(foo, bar) { console.log("第1个监听事件,参数foo=" + foo + ",bar="+bar ); });/* 看到API中removeListener移除方法时,以为应该是这样 但是结果^_^!!!!!*/ee.removeListener('some_events', function(){ console.log('成功移除事件some_events监听!'); }); console.log('第一轮'); ee.emit('some_events', 'Wilson', 'Zhong');
当我用emitter.on给some_events注册了一个监听后,我用emiiter.removeListener移除some_events的监听,随后再调用emitter.emit去触发,最后发现不是按我想像的在进行!为什么呢?
我理所当然的认为emiiter.removeListener第二个参数是个回调函数,API还是要认真看清楚啊!!!
下面再看个成功的场景~~~
var EventEmitter = require('events').EventEmitter; var ee = new EventEmitter();var listener = function(foo,bar) { console.log("第1个监听事件,参数foo=" + foo + ",bar="+bar ); }var listener2= function(foo,bar) { console.log("第2个监听事件,参数foo=" + foo + ",bar="+bar ); }var listener3= function(foo,bar) { console.log("第3个监听事件,参数foo=" + foo + ",bar="+bar ); } ee.on('some_events', listener); ee.on('some_events', listener2); ee.on('some_events', listener3);/* EventEmitter.removeListener(event, listener) 移除指定事件的监听器 注意:该监听器必须是注册过的 PS:上一个例子之后以会失败,很大原因就是忽略了监听器,理所当然的认为传个事件名就OK了,所以就悲剧了!*/ee.removeListener('some_events', listener); ee.removeListener('some_events', listener3); ee.emit('some_events', 'Wilson', 'Zhong');
我用示例中写法,给some_events添加了三个监听,又移除了第一个和第三个监听,最后再用emitter.emit触发some_events,输出结果不难发现,用emitter.removeListener移除的第一个和第三个监听都没有再起作用,
想当然是害人地,原来emitter.removeListener的第二个参数是要移除的监听,而非移除成功后的回调函数……^_^!
emitter.removeAllListeners([event])
emitter.removeListener用过了,但一个事件可以有多个监听,需要全部移除时,一个个移除明显不是愉快的做法,不符合偷懒的天性!
让我们来体验一下emitter.removeAllListeners带来的便捷!
var EventEmitter = require('events').EventEmitter; var ee = new EventEmitter();var listener = function(foo,bar) { console.log("第1个监听事件,参数foo=" + foo + ",bar="+bar ); }var listener2= function(foo,bar) { console.log("第2个监听事件,参数foo=" + foo + ",bar="+bar ); } ee.on('some_events', listener); ee.on('some_events', listener2); ee.on('other_events',function(foo,bar) { console.log("其它监听事件,参数foo=" + foo + ",bar="+bar ); });/* EventEmitter.removeAllListeners([event]) 移除(批定事件)所有监听器 参数1:可选参数,event 字符串,事件名*/ee.removeAllListeners('some_events'); ee.emit('some_events', 'Wilson', 'Zhong'); ee.emit('other_events', 'Wilson', 'Zhong');
看看上面的执行结果,你会发现给some_events注册了两个监听;给other_events注册了一个监听;我调用emitter.removeAllListeners传了some_events事件名;
最后使用emitter.on函数触发some_events和other_events两个事件,最后发现some_events注册的两个监听都不存在,而other_events注册的监听还存在;
这表示当 emitter.removeAllListeners传用事件名作为参数时,为移除传入事件名的所有监听,而不会影响其它事件监听!
emitter.removeAllListeners可以不传用事件名参数;直接执行
var EventEmitter = require('events').EventEmitter; var ee = new EventEmitter();var listener = function(foo,bar) { console.log("第1个监听事件,参数foo=" + foo + ",bar="+bar ); }var listener2= function(foo,bar) { console.log("第2个监听事件,参数foo=" + foo + ",bar="+bar ); } ee.on('some_events', listener); ee.on('some_events', listener2); ee.on('other_events',function(foo,bar) { console.log("其它监听事件,参数foo=" + foo + ",bar="+bar ); });/* EventEmitter.removeAllListeners([event]) 移除(批定事件)所有监听器 参数1:可选参数,event 字符串,事件名*/ee.removeAllListeners(); ee.emit('some_events', 'Wilson', 'Zhong'); ee.emit('other_events', 'Wilson', 'Zhong');
示例代码和传入参数时几乎一样,只是在调用emitter.removeAllListeners并没有传入指定事件名;
运行结果会发现some_events和other_events所有监听都不存在了,它会移除所有监听!(比较暴力的方法一般要慎用~~)
emitter.listeners(event)
var EventEmitter = require('events').EventEmitter; var ee = new EventEmitter();var listener = function(foo,bar) { console.log("第1个监听事件,参数foo=" + foo + ",bar="+bar ); }var listener2= function(foo,bar) { console.log("第2个监听事件,参数foo=" + foo + ",bar="+bar ); } ee.on('some_events', listener); ee.on('some_events', listener2); ee.on('other_events',function(foo,bar) { console.log("其它监听事件,参数foo=" + foo + ",bar="+bar ); });/* EventEmitter.listeners(event) //返回指定事件的监听数组 参数1:event 字符串,事件名 */var listenerEventsArr = ee.listeners('some_events'); console.log(listenerEventsArr.length)for (var i = listenerEventsArr.length - 1; i >= 0; i--) { console.log(listenerEventsArr[i]); };
给some_events注册两个监听,调用emitter.listeners函数,传入some_events事件名,接收函数返回值;
从结果可以看出,返回值接收到some_events所有注册监听的集合!
emitter.setMaxListeners(n)
一个事件可以添加多个监听是没错,但Nodejs默认最大值是多少呢?
var EventEmitter = require('events').EventEmitter; var ee = new EventEmitter();/* 给EventEmitter 添加11个监听*/for (var i = 10; i >= 0; i--) { ee.on('some_events',function() { console.log('第'+ (i +1) +'个监听'); }); };
添加N个监听示例源码
上面示例中我用个循环给some_events添加11个监听,执行代码,发现warning信息出现,并且提示的比较详细了,需要用emitter.setMaxListeners()去提升限值
var EventEmitter = require('events').EventEmitter; var ee = new EventEmitter();/* EventEmitter.setMaxListeners (n) 给EventEmitter设置最大监听 参数1: n 数字类型,最大监听数 超过10个监听时,不设置EventEmitter的最大监听数会提示: (node) warning: possible EventEmitter memory leak detected. 11 listeners added. Use emitter.setMaxListeners() to increase limit. 设计者认为侦听器太多,可能导致内存泄漏,所以存在这样一个警告*/ee.setMaxListeners(15);/* 给EventEmitter 添加11个监听*/for (var i = 10; i >= 0; i--) { ee.on('some_events',function() { console.log('第'+ (i +1) +'个监听'); }); };
当我调用emitter.setMaxListeners传入15时,执行代码,warning信息不再出现;
emitter.setMaxListeners的作用是给EventEmitter设置最大监听数,感觉一般是不需要设置这个值,10个还不够用的情况应该是比较少了!
设计者认为侦听器太多会导致内存泄漏,所有就给出了一个警告!
其它...
用的比较少的就不详细说了
EventEmitter.defaultMaxListeners
EventEmitter.defaultMaxListeners功能与setMaxListeners类似,
给所有EventEmitter设置最大监听
setMaxListeners优先级大于defaultMaxListeners
EventEmitter.listenerCount(emitter, event)
返回指定事件的监听数
特殊的事件Error
引用自Node.js开发指南:EventEmitter 定义了一个特殊的事件 error,它包含了“错误”的语义,我们在遇到 异常的时候通常会发射 error 事件。当 error 被发射时,EventEmitter 规定如果没有响 应的监听器,Node.js 会把它当作异常,退出程序并打印调用栈。我们一般要为会发射 error 事件的对象设置监听器,避免遇到错误后整个程序崩溃。
事件的继承
以后归到util里再讲一下吧,有兴趣的可以自已看看 http://nodejs.org/api/util.html#util_util_inherits_constructor_superconstructor
【推荐学习:《nodejs 教程》】
以上是nodejs中事件模块提供了哪个对象的详细内容。更多信息请关注PHP中文网其他相关文章!

React受欢迎的原因包括其性能优化、组件复用和丰富的生态系统。1.性能优化通过虚拟DOM和diffing机制实现高效更新。2.组件复用通过可复用组件减少重复代码。3.丰富的生态系统和单向数据流增强了开发体验。

React是构建动态和交互式用户界面的首选工具。1)组件化与JSX使UI拆分和复用变得简单。2)状态管理通过useState钩子实现,触发UI更新。3)事件处理机制响应用户交互,提升用户体验。

React是前端框架,用于构建用户界面;后端框架用于构建服务器端应用程序。React提供组件化和高效的UI更新,后端框架提供完整的后端服务解决方案。选择技术栈时需考虑项目需求、团队技能和可扩展性。

HTML和React的关系是前端开发的核心,它们共同构建现代Web应用的用户界面。1)HTML定义内容结构和语义,React通过组件化构建动态界面。2)React组件使用JSX语法嵌入HTML,实现智能渲染。3)组件生命周期管理HTML渲染,根据状态和属性动态更新。4)使用组件优化HTML结构,提高可维护性。5)性能优化包括避免不必要渲染,使用key属性,保持组件单一职责。

React是构建交互式前端体验的首选工具。1)React通过组件化和虚拟DOM简化UI开发。2)组件分为函数组件和类组件,函数组件更简洁,类组件提供更多生命周期方法。3)React的工作原理依赖虚拟DOM和调和算法,提高性能。4)状态管理使用useState或this.state,生命周期方法如componentDidMount用于特定逻辑。5)基本用法包括创建组件和管理状态,高级用法涉及自定义钩子和性能优化。6)常见错误包括状态更新不当和性能问题,调试技巧包括使用ReactDevTools和优

React是一个用于构建用户界面的JavaScript库,其核心是组件化和状态管理。1)通过组件化和状态管理简化UI开发。2)工作原理包括调和和渲染,优化可通过React.memo和useMemo实现。3)基本用法是创建并渲染组件,高级用法包括使用Hooks和ContextAPI。4)常见错误如状态更新不当,可使用ReactDevTools调试。5)性能优化包括使用React.memo、虚拟化列表和CodeSplitting,保持代码可读性和可维护性是最佳实践。

React通过JSX与HTML结合,提升用户体验。1)JSX嵌入HTML,使开发更直观。2)虚拟DOM机制优化性能,减少DOM操作。3)组件化管理UI,提高可维护性。4)状态管理和事件处理增强交互性。

React组件可以通过函数或类定义,封装UI逻辑并通过props接受输入数据。1)定义组件:使用函数或类,返回React元素。2)渲染组件:React调用render方法或执行函数组件。3)复用组件:通过props传递数据,构建复杂UI。组件的生命周期方法允许在不同阶段执行逻辑,提升开发效率和代码可维护性。


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

安全考试浏览器
Safe Exam Browser是一个安全的浏览器环境,用于安全地进行在线考试。该软件将任何计算机变成一个安全的工作站。它控制对任何实用工具的访问,并防止学生使用未经授权的资源。

EditPlus 中文破解版
体积小,语法高亮,不支持代码提示功能

DVWA
Damn Vulnerable Web App (DVWA) 是一个PHP/MySQL的Web应用程序,非常容易受到攻击。它的主要目标是成为安全专业人员在合法环境中测试自己的技能和工具的辅助工具,帮助Web开发人员更好地理解保护Web应用程序的过程,并帮助教师/学生在课堂环境中教授/学习Web应用程序安全。DVWA的目标是通过简单直接的界面练习一些最常见的Web漏洞,难度各不相同。请注意,该软件中

Dreamweaver CS6
视觉化网页开发工具

适用于 Eclipse 的 SAP NetWeaver 服务器适配器
将Eclipse与SAP NetWeaver应用服务器集成。