站長資訊網
最全最豐富的資訊網站

Node.js的內置模塊 event,利用它怎么實現發布訂閱模式

對于發布訂閱模式想必大家并不陌生,它在異步交互中具有很大的作用,能夠使我們的代碼結構更加清晰易讀,便于維護。

Node.js的內置模塊 event,利用它怎么實現發布訂閱模式

node.js極速入門課程:進入學習

node中我們可以使用 內置模塊event 來實現發布訂閱模式,這篇文章我們將深入去學習event并演示它在我們實際開發中的作用,讓我們開始吧!【相關教程推薦:nodejs視頻教程】

一、初步使用

引入event內置模塊

// 引入內置模塊event const EventEmitter = require("events");

創建event對象

event內置模塊本質是一個構造函數,我們需要通過new操作符去調用它

// 創建event對象 const event = new EventEmitter();

監聽事件

使用event對象上的on函數來定義一個監聽事件,語法為:event.on(事件名,事件處理函數)

// 監聽run事件 event.on("run", (data) => {     console.log("run事件運行,參數為:", data); });

觸發事件

使用event對象上的emit函數來觸發監聽的事件,語法為:event.emit(需要觸發的事件名,需要給事件處理函數傳遞的參數)

// 觸發run事件 event.emit("run", "111111");

完整代碼

// 引入內置模塊event const EventEmitter = require("events"); // 創建event對象 const event = new EventEmitter();  // 監聽run事件 event.on("run", (data) => {     console.log("run運行,參數為:", data); });  // 觸發run事件 event.emit("run", "111111");

運行結果:

Node.js的內置模塊 event,利用它怎么實現發布訂閱模式

❗️ 事件重復監聽的問題

==注意:當同一事件被監聽多次時,觸發事件時會同時觸發這個事件的所有事件處理函數==

Node.js的內置模塊 event,利用它怎么實現發布訂閱模式

二、應用

在上一節Node.js | 搭建后端服務器(含內置模塊 http | url | querystring 的使用)中有一個使用node模擬get請求(轉發跨域數據)的案例:

const http = require("http"); const https = require("https"); // http和https的區別僅在于一個是http協議一個是https協議 const url = require("url");  const server = http.createServer();  server.on("request", (req, res) => {     const urlObj = url.parse(req.url, true);      res.writeHead(200, {         "content-type": "application/json;charset=utf-8",         "Access-Control-Allow-Origin": "http://127.0.0.1:5500",     });      switch (urlObj.pathname) {         case "/api/maoyan":             // 我們定義的httpget方法:使node充當客戶端去貓眼的接口獲取數據             httpget((data) => res.end(data)); // 注意這里             break;          default:             res.end("404");             break;     } });  server.listen(3000, () => {     console.log("服務器啟動啦!"); });  function httpget(cb) {     // 定義一個存放數據的變量     let data = "";     // 因為貓眼的接口是https協議的,所以我們需要引入https     // http和https都具有一個get方法能夠發起get請求,區別是一個是http協議,一個是https協議     // http get方法第一個參數為接口地址,第二個參數為回調函數     https.get(         "https://i.maoyan.com/api/mmdb/movie/v3/list/hot.json?ct=%E8%A5%BF%E5%8D%8E&ci=936&channelId=4",         (res) => {             // http get方法獲取的數據是一點點返回的,并不是直接返回全部             // 監聽data,當有數據返回時就會被調用             res.on("data", (chunk) => {                 // 收集數據                 data += chunk;             });             // 監聽end,數據返回完畢后調用             res.on("end", () => {                 cb(data); // 注意這里             });         }     ); }

注意上面代碼的第19行和第49行:

httpget((data) => res.end(data)); // 注意這里
cb(data); // 注意這里

這個例子中,我們是通過在httpget函數中傳入一個回調函數來接收httpget函數獲取到的數據,這種寫法實際是沒有問題的,在開發中也常常進行使用。

但在一些情況下,特別是函數多層嵌套調用時(如下面的例子),這種寫法就顯得不夠優雅,因為它的代碼結構不是很清晰,不能很直觀的看懂其邏輯:

function user() {     getUser((data) => {         console.log(data);     }); }  function getUser(cb) {     // ....     const id = 1;     getUserInfo(cb, id); }  function getUserInfo(cb, id) {     // ....     const name = id + "Ailjx";     cb(name); }

讓我們使用內置模塊event去改造一下上面node模擬get請求(轉發跨域數據)的案例:

const http = require("http"); const https = require("https"); const url = require("url"); const EventEmitter = require("events"); const server = http.createServer();  // 存放event對象 let event = "";  server.on("request", (req, res) => {     const urlObj = url.parse(req.url, true);      res.writeHead(200, {         "content-type": "application/json;charset=utf-8",         "Access-Control-Allow-Origin": "http://127.0.0.1:5500",     });      switch (urlObj.pathname) {         case "/api/maoyan":             event = new EventEmitter(); // 注意該位置             // 監聽事件             event.on("resEnd", (data) => {                 res.end(data);             });             httpget();             break;          default:             res.end("404");             break;     } });  server.listen(3000, () => {     console.log("服務器啟動啦!"); });  function httpget() {     let data = "";     https.get(         "https://i.maoyan.com/api/mmdb/movie/v3/list/hot.json?ct=%E8%A5%BF%E5%8D%8E&ci=936&channelId=4",         (res) => {             res.on("data", (chunk) => {                 data += chunk;             });             res.on("end", () => {                 // 觸發事件并傳遞數據                 event.emit("resEnd", data);             });         }     ); }

運行并調用/api/maoyan接口:

Node.js的內置模塊 event,利用它怎么實現發布訂閱模式

接口正常使用

注意上邊代碼new EventEmitter()的位置,如果new EventEmitter()是在外部的話,相當于是只有一個全局的event對象,當我們每次調用/api/maoyan接口時,node都會監聽一個新的resEnd事件,這就會導致resEnd事件被重復監聽

Node.js的內置模塊 event,利用它怎么實現發布訂閱模式

所以我們才需要將創建event對象的代碼new EventEmitter()寫到接口的case分支里,這樣當我們調用這個接口時,會創建一個新的event對象,老的event對象被棄用會被JS垃圾處理機制給處理掉,這樣就不會出現resEnd事件被重復監聽的問題

贊(0)
分享到: 更多 (0)
網站地圖   滬ICP備18035694號-2    滬公網安備31011702889846號
久久久国产精品va麻豆| 久99频这里只精品23热视频| 国产偷窥熟女精品视频| 久久亚洲精品无码av| 久久精品国产免费观看 | 2022久久国产精品免费热麻豆| 国内精品久久久久久久97牛牛| 国产精品99久久久久久www| 日韩免费观看的一级毛片| 日韩人妻无码一区二区三区久久99 | 国产精品白丝在线观看有码| 精品日韩亚洲AV无码| 久久久999国产精品| 亚洲国产精品VA在线看黑人| 国产精品无码久久综合| 亚洲精品无码不卡在线播HE| 人妻少妇精品一区二区三区| 久久夜色撩人精品国产| 国产精品亚洲视频| 国产精品美女久久久久av爽| 一级做a爰黑人又硬又粗免费看51社区国产精品视 | 亚洲精品91在线| 2021国产精品自在拍在线播放| 久久精品中文字幕无码绿巨人| 亚洲自偷自偷精品| 精品国产福利片在线观看| 亚洲日韩国产精品无码av| 91精品国产入口| 亚洲精品视频观看| 国产精品美女久久久| 色综合久久精品中文字幕首页| 国产精品久久久久久久久| 999国内精品永久免费观看| 国产成人精品18| 精品人人妻人人澡人人爽牛牛| 成人h动漫精品一区二区无码 | 精品国产一区二区三区在线观看 | 自拍偷在线精品自拍偷99| 亚洲AV永久无码精品一福利| 国产SUV精品一区二区四| 国产精品女人在线观看|