如何正確使用Node.js事件

事件驅動的編程變得流行之前,在程序內部進行通信的標準方法非常簡單:如果一個組件想要向另外一個發送消息,只是顯式地調用了那個組件上的方法。愛掏網 - it200.com但是在 react 中用的卻是事件驅動而不是調用愛掏網 - it200.com

事件的好處

這種方法能夠使
組件更加分離。愛掏網 - it200.com在我們繼續寫程序時,會識別整個過程中的事件,在正確的時間觸發它們,并為每個事件附加一個或多個事件監聽器,這使得功能擴展變得更加容易。愛掏網 - it200.com我們可以為特定事件添加更多的 listener,而不必修改現有的偵聽器或觸發事件的應用程序部分。愛掏網 - it200.com我們所談論的是觀察者模式。愛掏網 - it200.com

設計一個事件驅動的體系結構

對事件進行識別非常重要,我們不希望最終必須從系統中刪除或替換現有事件,因為這可能會迫使我們刪除或修改附加到事件上的眾多偵聽器。愛掏網 - it200.com我的一般原則是僅在業務邏輯單元完成執行時才考慮觸發事件。愛掏網 - it200.com

假如你想在用戶注冊后發送一堆不同的電子郵件。愛掏網 - it200.com注冊過程本身可能會涉及許多復雜的步驟和查詢,但從商業角度來看,這只是其中的一個步驟愛掏網 - it200.com每個要發送的電子郵件也是單獨的步驟。愛掏網 - it200.com因此,一旦注冊完成馬上就發布事件是很有意義的。愛掏網 - it200.com于是我們附加了多個監聽器,每個監聽器負責發送一種類型的電子郵件。愛掏網 - it200.com

Node的異步事件驅動架構具有一些被稱為“emitters”的對象。愛掏網 - it200.com它們發出命名事件,這些事件會調用被稱為“listener”的函數。愛掏網 - it200.com發出事件的所有對象都是 EventEmitter 類的實例。愛掏網 - it200.com使用它,我們可以創建自己的事件:

一個例子

讓我們使用內置的 events 模塊(我建議你查看這個文檔:nodejs.org/api/events.… EventEmitter 的訪問權限。愛掏網 - it200.com

const EventEmitter = require('events');

const myEmitter = new EventEmitter();

module.exports = myEmitter;

這是我們的服務器端程序的一部分,它負責接收HTTP請求,保存新用戶并發出事件:

const myEmitter = require('./my_emitter');

// Perform the registration steps

// Pass the new user object as the message passed through by this event.
myEmitter.emit('user-registered', user);

附加一個監聽器的單獨模塊:

const myEmitter = require('./my_emitter');

myEmitter.on('user-registered', (user) => {
  // Send an email or whatever.
});

將策略與實現分開是一種非常好的做法。愛掏網 - it200.com在這種情況下,策略意味著哪些 listener 訂閱了哪些事件。愛掏網 - it200.com實現意味著 listener 自己。愛掏網 - it200.com

const myEmitter = require('./my_emitter');
const sendEmailOnRegistration = require('./send_email_on_registration');
const someOtherListener = require('./some_other_listener');

myEmitter.on('user-registered', sendEmailOnRegistration);
myEmitter.on('user-registered', someOtherListener);
module.exports = (user) => {
  // Send a welcome email or whatever.
}

這種分離使 listener 也可以被重復使用,它可以被附加到發送相同消息的其他事件上(用戶對象)。愛掏網 - it200.com同樣重要的是 當多個 listener 被附加到單個事件時,它們將按照附加的順序同步執行愛掏網 - it200.com因此 someOtherListener 將在 sendEmailOnRegistration 完成執行后運行。愛掏網 - it200.com

但是,如果你希望自己的 listener 以異步方式運行,只需用 setImmediate 包裝它們的實現,如下所示:

module.exports = (user) => {
  setImmediate(() => {
    // Send a welcome email or whatever.
  });
}

讓你的 Listeners 保持簡潔

在寫 listener 時要堅持單一責任原則。愛掏網 - it200.com一個 listener 應該只做一件事并把事情做好。愛掏網 - it200.com例如:要避免在 listener 中編寫太多的條件并根據事件傳來的數據(消息)去決定做什么。愛掏網 - it200.com在這種情況下使用不同的事件會更加合適:

const myEmitter = require('./my_emitter');

// Perform the registration steps

// The application should react differently if the new user has been activated instantly.
if (user.activated) {
  myEmitter.emit('user-registered:activated', user);

} else {
  myEmitter.emit('user-registered', user);
}
const myEmitter = require('./my_emitter');
const sendEmailOnRegistration = require('./send_email_on_registration');
const someOtherListener = require('./some_other_listener');
const doSomethingEntirelyDifferent = require('./do_something_entirely_different');

myEmitter.on('user-registered', sendEmailOnRegistration);
myEmitter.on('user-registered', someOtherListener);

myEmitter.on('user-registered:activated', doSomethingEntirelyDifferent);
view raw

必要時明確分離 Listener

在前面的例子中,我們的 listener 是完全獨立的函數。愛掏網 - it200.com但是在 listener 與對象關聯的情況下(這時是一種方法),必須手動將其從已訂閱的事件中分離出來。愛掏網 - it200.com否則對象將永遠不會被垃圾回收,因為對象( listener )的一部分將會繼續被外部對象( emitter )引用,所以存在內存泄漏的可能。愛掏網 - it200.com

例如,如果我們正在開發一個聊天程序,并且希望當新消息到達用戶進入的聊天室時,顯示通知的功能應該位于該用戶對象本身的內部,我們可能會這樣做:

class ChatUser {

  displayNewMessageNotification(newMessage) {
    // Push an alert message or something.
  }

  // `chatroom` is an instance of EventEmitter.
  connectToChatroom(chatroom) {
    chatroom.on('message-received', this.displayNewMessageNotification);
  }

  disconnectFromChatroom(chatroom) {
    chatroom.removeListener('message-received', this.displayNewMessageNotification);
  }
}

當用戶關閉他的標簽或暫時斷開互聯網連接時,我們可能希望在服務器端發起一個回調,通知其他用戶有人剛剛下線。愛掏網 - it200.com當然在這時為脫機用戶調用 displayNewMessageNotification 沒有任何意義。愛掏網 - it200.com除非我們刪除它,否則它將繼續被用于調用新消息。愛掏網 - it200.com如果不這樣做,除了不必要的調用之外,用戶對象也會被永久地保留在內存中。愛掏網 - it200.com因此在用戶脫機時應該在服務器端回調中調用 disconnectFromChatroom愛掏網 - it200.com

注意事項

如果不小心,即便是松散耦合的事件驅動架構也會導致復雜性的增加,可能會導致在系統中跟蹤依賴關系變得很困難。愛掏網 - it200.com如果我們從偵聽器內部發出事件,程序會特別容易出現這類問題。愛掏網 - it200.com這可能會觸發意外的事件鏈。愛掏網 - it200.com

結語

感謝您的觀看,如有不足之處,歡迎批評指正。愛掏網 - it200.com
獲取資料

聲明:所有內容來自互聯網搜索結果,不保證100%準確性,僅供參考。如若本站內容侵犯了原著者的合法權益,可聯系我們進行處理。
發表評論
更多 網友評論0 條評論)
暫無評論

返回頂部

主站蜘蛛池模板: 久久精品亚洲中文字幕无码网站| 午夜国产在线观看| 福利片福利一区二区三区| 俺去啦在线观看| 日本里番全彩acg里番下拉式| jizz国产在线播放| 国产成人cao在线| 日韩精品无码免费专区网站| www.henhencao.com| 国产女人爽的流水毛片| 精品久久久久成人码免费动漫| 中文字幕25页| 国产女人aaa级久久久级| 日韩人妻无码精品无码中文字幕| 99久久人妻精品免费二区| 亚洲爆乳无码专区www| 国产精品欧美一区二区三区不卡| 福利国产微拍广场一区视频在线| chinese国产一区二区| 成人年无码AV片在线观看| 老司机久久影院| 人与禽交zozo| 少妇丰满爆乳被呻吟进入| 激情视频在线观看网站| xxxxx日韩| 啦啦啦在线免费视频| 日本娇小videos精品| 欧美激情另类自拍| 亚洲乱码卡三乱码新区| 国产精品无码免费视频二三区| 热の无码热の有码热の综合| 午夜性色吃奶添下面69影院| 亚洲国产三级在线观看| 国产香蕉一区二区精品视频| 漂亮诱人的女邻居| 风流老熟女一区二区三区| 久久精品国产2020| 免费看美女让人桶尿口| 国产拳头交一区二区| 日韩大片免费观看视频播放 | 综合久久久久久中文字幕|