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

有趣的Nodejs模块events

时间:2023-04-03 18:11:54 Node.js

阅读了events模块的文档,研究了几个有趣的问题:??事件驱动模型??优雅的错误处理??Listener队列顺序处理??内存管理与防泄漏引用/转载请声明出处:原文链接:xxoo521.com事件驱动模型Nodejs采用事件驱动、非阻塞IO模型。事件模块是事件驱动的核心模块。许多内置模块扩展了events.EventEmitter。你不需要手动实现这个设计模式,直接继承EventEmitter即可。代码如下:const{EventEmitter}=require("events");classMyEmitterextendsEventEmitter{}constins=newMyEmitter();ins.on("test",()=>{console.log("发出测试事件");});ins.emit("test");优雅的错误处理根据文档,EventEmitter实例的错误事件应该是一个特殊事件。推荐的做法是:创建实例后,应立即注册错误事件。constins=newMyEmitter();ins.on("error",error=>{console.log("errormsgis",error.message);});注册了error事件后,我原来的理解是事件回调逻辑中的所有Error都会被EventEmitter内部捕获,在内部触发error事件。也就是说,下面的代码会打印:“errormsgisaisaisnotdefined”。ins.on("test",()=>{console.log(a);});ins.emit("test");但是并没有捕获到错误,直接抛出异常。可以看出,EventEmitter在执行内部逻辑时是没有try-catch的。为此,请参阅节点问题。简单的说,Error和Exception并不完全一样。如果按照正常的思路,不想每次都在外面放一层try-catch,怎么办?我的做法是在EventEmitter原型链中添加一个safeEmit函数。EventEmitter.prototype.safeEmit=function(name,...args){尝试{returnthis.emit(name,...args);}catch(error){returnthis.emit("错误",错误);}};这样,运行上一段代码的Exception就会被捕获,并触发error事件。上一段代码的输出变成:errormsgisaisaisaisnotdefinedListenerqueueorderprocessing对于同一个事件,当它被触发时,函数的执行顺序就是函数被绑定的顺序。官方库提供了emitter.prependListener()和emitter.prependOnceListener()两个接口,可以让新的监听器直接添加到队列的头部。但是,如果您希望将新的侦听器放置在任何侦听器队列中的任何位置怎么办?insertListener方法封装在原型链上。EventEmitter.prototype.insertListener=function(name,index,callback,once=false){//如果是once监听器,它的数据结构是{listener:Function}//普通监听器,直接Functionconstlisteners=ins.rawListeners(名称);常量那个=这个;//下标无效if(index>listeners.length||index<0){returnfalse;}//绑定监听器数量已达到上限if(listeners.length>=this.getMaxListeners()){returnfalse;}listeners.splice(index,0,once?{listener:callback}:callback);this.removeAllListeners(名字);listeners.forEach(function(item){if(typeofitem==="function"){that.on(name,item);}else{const{listener}=item;that.once(name,listener);}});返回真;};如下:constins=newMyEmitter();ins.on("error",error=>{console.log("errormsgis",error.message);});ins.on("test",()=>{console.log("测试1");});ins.on("测试",()=>{console.log("test2");});//向监听队列插入一个新的监听,一个是once类型,一个不是类型ins.insertListener("test",0,()=>{console.log("一次测试插入");},true);ins.insertListener("test",1,()=>{console.log("测试插入");});连续调用两次Ins.emit("test"),结果输出如下:#第一次oncetestinserttestinserttest1test2#第二次:once类型监听器调用并销毁testinserttest1test2内存管理和泄漏绑定中的预防当使用事件监听器时,如果监听器没有被移除,则存在内存泄漏的风险。我知道的常见做法是:经常CR,去掉不需要的事件监听器,通过一次绑定监听器。调用一次后,listener自动移除[推荐]hack更安全的EventEmitter参考链接NodeJSIssueDocs:专注于前端和算法的events系列干货分享,欢迎关注(???)