当前位置: 首页 > 后端技术 > Node.js

NodeJSEvents必须要知道

时间:2023-04-03 13:35:05 Node.js

1。环境节点8.11.32。基本使用//01.jsconstEventEmitter=require('events');classMyEmitterextendsEventEmitter{}constmyEmitter=newMyEmitter();myEmitter.on('event',()=>{console.log('anevent发生了!');});myEmitter.emit('事件');输出:事件发生!3.将其传递给emit()方法可以传递无限数量的参数。除了箭头函数之外,在回调函数内部,这将绑定到EventEmitter类的实例//02.jsconstEventEmitter=require('events')classMyEmitterextendsEventEmitter{}constmyEmitter=newMyEmitter()myEmitter.on('event',function(a,b){console.log(a,b,this,this===myEmitter)})myEmitter.on('event',(a,b)=>{console.log(a,b,this,this===myEmitter)})myEmitter.emit('event','a',{name:'wdd'})输出:a{name:'wdd'}MyEmitter{domain:null,_events:{event:[[Function],[Function]]},_eventsCount:1,_maxListeners:undefined}truea{name:'wdd'}{}false4.同步或异步调用监听器?emit()方法会同步跟随事件注册顺序执行回调//03.jsconstEventEmitter=require('events')classMyEmitterextendsEventEmitter{}constmyEmitter=newMyEmitter()myEmitter.on('event',()=>{console.log('01一个事件发生了!')})myEmitter.on('event',()=>{console.log('02一个事件发生了!')})console.log(1)myEmitter.emit('event')console.log(2)output:101一个事件发生了!02事件发生!2深入思考,为什么要事件回调同步?异步有什么问题?同步调用事件监听器可以保证事件监听器按照注册的先后顺序被调用,避免竞争条件和逻辑错误。5.如何只订阅一次事件?使用一次只订阅一次事件//04.jsconstEventEmitter=require('events')classMyEmitterextendsEventEmitter{}constmyEmitter=newMyEmitter()letm=0myEmitter.once('event',()=>{console.log(++m)})myEmitter.emit('event')myEmitter.emit('event')6.如果不订阅,error事件error是一个特殊的事件名。当这个事件被触发时,如果没有对应的事件监听器,程序就会崩溃。events.js:183抛出错误;//未处理的'error'事件^Error:在Object.(/Users/xxx/github/node-note/events/05.js:12:25)在Module进行测试。_compile(module.js:635:30)在Object.Module._extensions..js(module.js:646:10)在Module.load(module.js:554:32)在tryModuleLoad(module.js:497:12)在Function.Module._load(module.js:489:3)在Function.Module.runMain(module.js:676:10)在启动时(bootstrap_node.js:187:16)在bootstrap_node.js:608:3因此,最好始终向EventEmitter实例添加一个错误监听器>{console.log(err)})console.log(1)myEmitter.emit('error',newError('test'))console.log(2)7.内部事件newListener和removeListenernewListener和removeListener是EventEmitter的实例对于内置事件,最好不要使用与自定义事件名称相同的名称。newListener在订阅者添加到订阅列表之前触发removeListener在订阅者从订阅列表中移除之后触发//06.jsconstEventEmitter=require('events')classMyEmitterextendsEventEmitter{}constmyEmitter=newMyEmitter()myEmitter.on('newListener',(event,listener)=>{console.log('----')console.log(event)console.log(listener)})myEmitter.on('myEmitter',(err)=>{console.log(err)})输出:从输出可以看出,即使没有触发myEmitter事件,on()方法也会触发newListener事件。----myEmitter[功能]8。事件监听器数量限制myEmitter.listenerCount('event'):用于计算实例上某个事件的监听器数量EventEmitter.defaultMaxListeners:EventEmitter类默认的最大监听器数量,默认为10个。如果超过,会输出警告。myEmitter.getMaxListeners():EventEmitter实例中一个事件的默认最大监听数,默认为10。如果超过,将输出警告。myEmitter.eventNames():一个EventEmitter实例返回多少个事件,一个EventEmitter实例最大监听数为10。这不是硬性规定,而是一个推荐值。可以通过setMaxListeners()接口更改此值。更改EventEmitter的最大侦听器数量将影响所有EventEmitter实例。更改EventEmitter实例的最大侦听器数量只会影响实例本身。如果没有必要,最好不要更改默认的侦听器数量限制。事件侦听器的数量是节点检测内存泄漏的标准维度。EventEmitter实例的最大侦听器数量不是一个实例的侦听器总数。比如同一个实例有5个A类事件的监听器,6个B类事件的监听器,则不会有告警。如果类型A有11个监听器,会有报警提示。如果你发现事件中有类似PossibleEventEmittermemoryleakdetected的告警,你需要知道如何从最大事件监听数的角度排查问题。//07.jsconstEventEmitter=require('events')classMyEmitterextendsEventEmitter{}constmyEmitter=newMyEmitter()constmaxListeners=11for(leti=0;i{console.log(err,1)})}myEmitter.on('event1',(err)=>{console.log(err,11)})console.log(myEmitter.listenerCount('event'))console.log(EventEmitter.defaultMaxListeners)console.log(myEmitter.getMaxListeners())console.log(myEmitter.eventNames())输出:111010['event','event1'](node:23957)MaxListenersExceededWarning:检测到可能的EventEmitter内存泄漏。添加了11个事件侦听器。使用emitter.setMaxListeners()增加限制