成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

NodeJS Events 必知必會(huì)

bladefury / 2805人閱讀

摘要:超過(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" } {} false
4. 同步還是異步調(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ān)文章

  • 前端必知必會(huì)HTTP請(qǐng)求系列(二)簡(jiǎn)單一點(diǎn)的HTTP協(xié)議

    摘要:通過(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ù)器之間的...

    xbynet 評(píng)論0 收藏0
  • 前端必知必會(huì)HTTP請(qǐng)求系列(三)HTTP報(bào)文內(nèi)的http信息

    摘要:報(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)文...

    Invoker 評(píng)論0 收藏0
  • java必知必會(huì)之SecureSocket

    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...

    kidsamong 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<