亚洲最大看欧美片,亚洲图揄拍自拍另类图片,欧美精品v国产精品v呦,日本在线精品视频免费

  • 站長資訊網(wǎng)
    最全最豐富的資訊網(wǎng)站

    Node.js的內(nèi)置模塊 event,利用它怎么實現(xiàn)發(fā)布訂閱模式

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

    Node.js的內(nèi)置模塊 event,利用它怎么實現(xiàn)發(fā)布訂閱模式

    node.js極速入門課程:進(jìn)入學(xué)習(xí)

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

    一、初步使用

    引入event內(nèi)置模塊

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

    創(chuàng)建event對象

    event內(nèi)置模塊本質(zhì)是一個構(gòu)造函數(shù),我們需要通過new操作符去調(diào)用它

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

    監(jiān)聽事件

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

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

    觸發(fā)事件

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

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

    完整代碼

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

    運行結(jié)果:

    Node.js的內(nèi)置模塊 event,利用它怎么實現(xiàn)發(fā)布訂閱模式

    ❗️ 事件重復(fù)監(jiān)聽的問題

    ==注意:當(dāng)同一事件被監(jiān)聽多次時,觸發(fā)事件時會同時觸發(fā)這個事件的所有事件處理函數(shù)==

    Node.js的內(nèi)置模塊 event,利用它怎么實現(xiàn)發(fā)布訂閱模式

    二、應(yīng)用

    在上一節(jié)Node.js | 搭建后端服務(wù)器(含內(nèi)置模塊 http | url | querystring 的使用)中有一個使用node模擬get請求(轉(zhuǎn)發(fā)跨域數(shù)據(jù))的案例:

    const http = require("http"); const https = require("https"); // http和https的區(qū)別僅在于一個是http協(xié)議一個是https協(xié)議 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充當(dāng)客戶端去貓眼的接口獲取數(shù)據(jù)             httpget((data) => res.end(data)); // 注意這里             break;          default:             res.end("404");             break;     } });  server.listen(3000, () => {     console.log("服務(wù)器啟動啦!"); });  function httpget(cb) {     // 定義一個存放數(shù)據(jù)的變量     let data = "";     // 因為貓眼的接口是https協(xié)議的,所以我們需要引入https     // http和https都具有一個get方法能夠發(fā)起get請求,區(qū)別是一個是http協(xié)議,一個是https協(xié)議     // http get方法第一個參數(shù)為接口地址,第二個參數(shù)為回調(diào)函數(shù)     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方法獲取的數(shù)據(jù)是一點點返回的,并不是直接返回全部             // 監(jiān)聽data,當(dāng)有數(shù)據(jù)返回時就會被調(diào)用             res.on("data", (chunk) => {                 // 收集數(shù)據(jù)                 data += chunk;             });             // 監(jiān)聽end,數(shù)據(jù)返回完畢后調(diào)用             res.on("end", () => {                 cb(data); // 注意這里             });         }     ); }

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

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

    這個例子中,我們是通過在httpget函數(shù)中傳入一個回調(diào)函數(shù)來接收httpget函數(shù)獲取到的數(shù)據(jù),這種寫法實際是沒有問題的,在開發(fā)中也常常進(jìn)行使用。

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

    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); }

    讓我們使用內(nèi)置模塊event去改造一下上面node模擬get請求(轉(zhuǎn)發(fā)跨域數(shù)據(jù))的案例:

    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(); // 注意該位置             // 監(jiān)聽事件             event.on("resEnd", (data) => {                 res.end(data);             });             httpget();             break;          default:             res.end("404");             break;     } });  server.listen(3000, () => {     console.log("服務(wù)器啟動啦!"); });  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", () => {                 // 觸發(fā)事件并傳遞數(shù)據(jù)                 event.emit("resEnd", data);             });         }     ); }

    運行并調(diào)用/api/maoyan接口:

    Node.js的內(nèi)置模塊 event,利用它怎么實現(xiàn)發(fā)布訂閱模式

    接口正常使用

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

    Node.js的內(nèi)置模塊 event,利用它怎么實現(xiàn)發(fā)布訂閱模式

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

    贊(0)
    分享到: 更多 (0)
    網(wǎng)站地圖   滬ICP備18035694號-2    滬公網(wǎng)安備31011702889846號