摘要:超過(guò)會(huì)有警告輸出。實(shí)例默認(rèn)的某個(gè)事件最大監(jiān)聽(tīng)者的數(shù)量,默認(rèn)是。事件監(jiān)聽(tīng)數(shù)量是檢測(cè)內(nèi)存泄露的一個(gè)標(biāo)準(zhǔn)一個(gè)維度。例如同一個(gè)實(shí)例類(lèi)型事件個(gè)監(jiān)聽(tīng)者,類(lèi)型事件個(gè)監(jiān)聽(tīng)者,這個(gè)并不會(huì)有告警。
1. 環(huán)境
node 8.11.3
2. 基本使用// 01.js const EventEmitter = require("events"); class MyEmitter extends EventEmitter {} const myEmitter = new MyEmitter(); myEmitter.on("event", () => { console.log("an event occurred!"); }); myEmitter.emit("event");
輸出:
an event occurred!3. 傳參與this指向
emit()方法可以傳不限制數(shù)量的參數(shù)。
除了箭頭函數(shù)外,在回調(diào)函數(shù)內(nèi)部,this會(huì)被綁定到EventEmitter類(lèi)的實(shí)例上
// 02.js const EventEmitter = require("events") class MyEmitter extends EventEmitter {} const myEmitter = new MyEmitter() 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 } true a { name: "wdd" } {} false4. 同步還是異步調(diào)用listeners?
emit()法會(huì)同步按照事件注冊(cè)的順序執(zhí)行回調(diào)
// 03.js const EventEmitter = require("events") class MyEmitter extends EventEmitter {} const myEmitter = new MyEmitter() myEmitter.on("event", () => { console.log("01 an event occurred!") }) myEmitter.on("event", () => { console.log("02 an event occurred!") }) console.log(1) myEmitter.emit("event") console.log(2)
輸出:
1 01 an event occurred! 02 an event occurred! 2
深入思考,為什么事件回調(diào)要同步?異步了會(huì)有什么問(wèn)題?
同步去調(diào)用事件監(jiān)聽(tīng)者,能夠確保按照注冊(cè)順序去調(diào)用事件監(jiān)聽(tīng)者,并且避免競(jìng)態(tài)條件和邏輯錯(cuò)誤。
5. 如何只訂閱一次事件?使用once去只訂閱一次事件
// 04.js const EventEmitter = require("events") class MyEmitter extends EventEmitter {} const myEmitter = new MyEmitter() let m = 0 myEmitter.once("event", () => { console.log(++m) }) myEmitter.emit("event") myEmitter.emit("event")6. 不訂閱,就發(fā)飆的錯(cuò)誤事件
error是一個(gè)特別的事件名,當(dāng)這個(gè)事件被觸發(fā)時(shí),如果沒(méi)有對(duì)應(yīng)的事件監(jiān)聽(tīng)者,則會(huì)導(dǎo)致程序崩潰。
events.js:183 throw er; // Unhandled "error" event ^ Error: test at Object.(/Users/xxx/github/node-note/events/05.js:12:25) at Module._compile (module.js:635:30) at Object.Module._extensions..js (module.js:646:10) at Module.load (module.js:554:32) at tryModuleLoad (module.js:497:12) at Function.Module._load (module.js:489:3) at Function.Module.runMain (module.js:676:10) at startup (bootstrap_node.js:187:16) at bootstrap_node.js:608:3
所以,最好總是給EventEmitter實(shí)例添加一個(gè)error的監(jiān)聽(tīng)器
const EventEmitter = require("events") class MyEmitter extends EventEmitter {} const myEmitter = new MyEmitter() myEmitter.on("error", (err) => { console.log(err) }) console.log(1) myEmitter.emit("error", new Error("test")) console.log(2)7. 內(nèi)部事件 newListener與removeListener
newListener與removeListener是EventEmitter實(shí)例的自帶的事件,你最好不要使用同樣的名字作為自定義的事件名。
newListener在訂閱者被加入到訂閱列表前觸發(fā)
removeListener在訂閱者被移除訂閱列表后觸發(fā)
// 06.js const EventEmitter = require("events") class MyEmitter extends EventEmitter {} const myEmitter = new MyEmitter() myEmitter.on("newListener", (event, listener) => { console.log("----") console.log(event) console.log(listener) }) myEmitter.on("myEmitter", (err) => { console.log(err) })
輸出:
從輸出可以看出,即使沒(méi)有去觸發(fā)myEmitter事件,on()方法也會(huì)觸發(fā)newListener事件。
---- myEmitter [Function]8. 事件監(jiān)聽(tīng)數(shù)量限制
myEmitter.listenerCount("event"): 用來(lái)計(jì)算一個(gè)實(shí)例上某個(gè)事件的監(jiān)聽(tīng)者數(shù)量
EventEmitter.defaultMaxListeners: EventEmitter類(lèi)默認(rèn)的最大監(jiān)聽(tīng)者的數(shù)量,默認(rèn)是10。超過(guò)會(huì)有警告輸出。
myEmitter.getMaxListeners(): EventEmitter實(shí)例默認(rèn)的某個(gè)事件最大監(jiān)聽(tīng)者的數(shù)量,默認(rèn)是10。超過(guò)會(huì)有警告輸出。
myEmitter.eventNames(): 返回一個(gè)實(shí)例上又多少種事件
EventEmitter和EventEmitter實(shí)例的最大監(jiān)聽(tīng)數(shù)量為10并不是一個(gè)硬性規(guī)定,只是一個(gè)推薦值,該值可以通過(guò)setMaxListeners()接口去改變。
改變EventEmitter的最大監(jiān)聽(tīng)數(shù)量會(huì)影響到所有EventEmitter實(shí)例
該變EventEmitter實(shí)例的最大監(jiān)聽(tīng)數(shù)量只會(huì)影響到實(shí)例自身
如無(wú)必要,最好的不要去改變默認(rèn)的監(jiān)聽(tīng)數(shù)量限制。事件監(jiān)聽(tīng)數(shù)量是node檢測(cè)內(nèi)存泄露的一個(gè)標(biāo)準(zhǔn)一個(gè)維度。
EventEmitter實(shí)例的最大監(jiān)聽(tīng)數(shù)量不是一個(gè)實(shí)例的所有監(jiān)聽(tīng)數(shù)量。
例如同一個(gè)實(shí)例A類(lèi)型事件5個(gè)監(jiān)聽(tīng)者,B類(lèi)型事件6個(gè)監(jiān)聽(tīng)者,這個(gè)并不會(huì)有告警。如果A類(lèi)型有11個(gè)監(jiān)聽(tīng)者,就會(huì)有告警提示。
如果在事件中發(fā)現(xiàn)類(lèi)似的告警提示Possible EventEmitter memory leak detected,要知道從事件最大監(jiān)聽(tīng)數(shù)的角度去排查問(wèn)題。
// 07.js const EventEmitter = require("events") class MyEmitter extends EventEmitter {} const myEmitter = new MyEmitter() const maxListeners = 11 for (let i = 0; i < maxListeners; i++) { myEmitter.on("event", (err) => { 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())
輸出:
11 10 10 [ "event", "event1" ] (node:23957) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 event listeners added. Use emitter.setMaxListeners() to increase limit
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/97169.html
摘要:通過(guò)請(qǐng)求和響應(yīng)的交換達(dá)成通信協(xié)議中已經(jīng)規(guī)定了請(qǐng)求是從客戶(hù)端發(fā)出,最后由服務(wù)端響應(yīng)這個(gè)請(qǐng)求并返回。隨后的字符串指明了請(qǐng)求訪(fǎng)問(wèn)的資源對(duì)象。協(xié)議自身不對(duì)請(qǐng)求和響應(yīng)之間的通信狀態(tài)進(jìn)行保存,也就是說(shuō)這個(gè)級(jí)別。從前發(fā)送請(qǐng)求后需等待并受到響應(yīng)。 showImg(https://segmentfault.com/img/bVbmDsG?w=1024&h=538); http協(xié)議用戶(hù)客戶(hù)端和服務(wù)器之間的...
摘要:報(bào)文用于協(xié)議交互的信息被稱(chēng)為報(bào)文?,F(xiàn)在出現(xiàn)的各種首部字段及狀態(tài)碼稍后會(huì)闡述。狀態(tài)碼響應(yīng)報(bào)文包含了多個(gè)范圍的內(nèi)容使用。如果服務(wù)器無(wú)法響應(yīng)范圍請(qǐng)求,則會(huì)返回狀態(tài)碼和完整的實(shí)體內(nèi)容。 showImg(https://segmentfault.com/img/bVbthNL?w=900&h=500); http報(bào)文 用于HTTP協(xié)議交互的信息被稱(chēng)為HTTP報(bào)文。請(qǐng)求端的http報(bào)文叫做請(qǐng)求報(bào)文...
SSL,Secure Sockets Layer,安全Socket層TLS,Transport Layer Security,傳輸層安全協(xié)議 package network.secure; import java.io.*; import javax.net.ssl.*; public class HTTPSClient { public static void main(Strin...
閱讀 2900·2019-08-30 15:55
閱讀 2009·2019-08-30 14:02
閱讀 1248·2019-08-29 15:23
閱讀 1014·2019-08-29 11:27
閱讀 468·2019-08-26 11:43
閱讀 3196·2019-08-26 10:32
閱讀 1261·2019-08-23 14:41
閱讀 3304·2019-08-23 14:41