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

Node常用内置模块(事件)

时间:2023-04-03 16:58:18 Node.js

node常用的内置模块(events)1.事件模块events通过EventEmitter类实现对事件的统一管理。常用API:on:添加事件监听emit:触发事件once:添加只触发一次的事件监听off:去掉具体监听代码display:constEventEmitter=require('events');constev=newEventEmitter();ev.once('start',(...args)=>{//只执行一次console.log('startonce',args);});ev.on('start',function(){console.log('tarton');console.log('this',this);})ev.emit('start','messagedata');//offletstartcb=()=>{console.log('jiang')}ev.on('startcb',startcb);ev.off('startcb',startcb);ev.emit('startcb');//不会被触发constfs=require('fs');//很多内置模块继承了EventEmitter类,可以直接使用该类的方法constcrt=fs.createReadStream();crt.on('data')2.发布-订阅模式定义了对象间的一对多依赖模式图:元素:缓存队列,存放订阅者信息,具有增加和订阅的能力。状态变化时通知所有订阅者进行监听模拟实现:.push(回调);}else{this._events[事件]=[回调];}}发布ish(event,...args){constitems=this._events[event];if(items&&items.length){items.forEach(callback=>{callback.call(this,...args);})}}}letps=newPubSub();ps.subscribe('event1',(...args)=>{console.log('event1runend',args);})ps.publish('event1','event1data')EventEmitter模拟实现:functionMyEvent(){//用户缓存订阅者信息this._events=Object.create(null);//创建一个没有任何原型的空对象}MyEvent.prototype.on=function(type,callback){this._events[type]=this._events[type]||}[];this._events[type].push(callback);}MyEvent.prototype.emit=function(type,...args){if(this._events[type]&&this._events[type].length){这个。_events[type].forEach(callback=>{callback.call(this,...args);})}else{console.log('Nosubscribers');}}MyEvent.prototype.off=function(type,callback){//判断当前类型的事件监听器是否存在,存在则取消指定的事件监听器if(this._events&&this._events[type]){this._events[type]=this._events[type].filter(cb=>{returncb!==callback&&cb.link!==callback;})}}MyEvent.prototype.once=function(type,callback){让cb=(...args)=>{callback.call(this,...args);这个。关闭(类型,cb);}cb.link=回调;this.on(type,cb);}letev=newMyEvent();letcb=function(...args){console.log(args);}ev.once('event1',cb);ev.off('event1',cb);//取消监听ev.emit('event1',1,2);ev.emit('event1',1,2);3.事件轮询eventloop是基于浏览器的事件轮询eventloop:从上到下执行所有同步代码执行,将遇到的宏任务和微任务依次添加到对应的任务队列中,同步代码执行完成后,执行满足条件的微任务,回调micro任务队列执行完后,执行所有满足条件的宏任务。回调执行事件轮询。注意:每次执行宏任务时,都会立即检查微任务队列。实践:setTimeout(()=>{console.log('s1');Promise.resolve().then(()=>{console.log('p2');})Promise.resolve().then(()=>{console.log('p3');})})Promise.resolve().then(()=>{console.log('p1');setTimeout(()=>{console.log('s2');})setTimeout(()=>{console.log('s3');})})//p1s1p2p3s2s3nodejseventloopeventloop:event轮询机制图:队列说明:定时器:执行setTimeout和setIntervalcallbackspendingcallbacks:执行系统操作的回调,例如:tcpudpidle,prepare:只在系统内部使用poll:执行I/O检查相关的回调:执行setImmediate中的回调closecallbacks:执行关闭事件的回调Nodejscomplete事件轮询:执行同步代码,将不同的任务添加到对应的队列中,当所有同步代码执行完成后,会执行所有满足添加的微任务的微任务代码,之后执行定时器队列中满足条件的宏任务.定时器中的宏任务全部执行完后(10版本前,任务队列未更改前),会依次切换队列。注意:每执行一次宏任务,都会先清除。'微任务代码,nextTick优先级高于promise练习一:setTimeout(()=>{console.log('s1');})Promise.resolve().then(()=>{console.log('p1');})console.log('start');process.nextTick(()=>{console.log('nextTick');});setImmediate(()=>{console.log('setImmediate');})console.log('end');//startendnextTickp1s1setImmediate练习2:setTimeout(()=>{console.log('s1');Promise.resolve().then(()=>{console.log('p1');})process.nextTick(()=>{console.log('t1');})})Promise.resolve().then(()=>{console.log('p2');})console.log('start');setTimeout(()=>{console.log('s2');Promise.resolve().then(()=>{console.log('p3');})process.nextTick(()=>{console.log('t2');})});控制台.log('end');//startendp2s1t1p1s2t2p3nodejs和浏览器事件轮询的区别任务队列数量不同每次执行完宏任务,都会清空微任务进程。nodejs中的nextTick优先promise.thennodejs事件轮询常见问题://setTimeout(()=>{//console.log('timeout');//})//虽然默认为0,但是时间片cpu的是不确定的,所以可能会在setImmediate之后入队//setImmediate(()=>{//console.log('immediate');//})//执行顺序不确定constfs=require('FS');飞秒。readFile('./m1.js',()=>{setTimeout(()=>{console.log('timeout');},0);setImmediate(()=>{console.log('immediate');})})//顺序确定,根据队列的先后顺序切换执行