溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

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

發(fā)布時間:2022-09-24 10:41:59 來源:億速云 閱讀:128 作者:iii 欄目:web開發(fā)

這篇文章主要介紹了怎么使用Node.js的內置模塊event實現(xiàn)發(fā)布訂閱模式的相關知識,內容詳細易懂,操作簡單快捷,具有一定借鑒價值,相信大家閱讀完這篇怎么使用Node.js的內置模塊event實現(xiàn)發(fā)布訂閱模式文章都會有所收獲,下面我們一起來看看吧。

一、初步使用

引入event內置模塊

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

創(chuàng)建event對象

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

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

監(jiān)聽事件

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

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

觸發(fā)事件

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

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

完整代碼

// 引入內置模塊event
const EventEmitter = require("events");
// 創(chuàng)建event對象
const event = new EventEmitter();

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

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

運行結果:

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

?? 事件重復監(jiān)聽的問題

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

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

二、應用

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

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充當客戶端去貓眼的接口獲取數據
            httpget((data) => res.end(data)); // 注意這里
            break;

        default:
            res.end("404");
            break;
    }
});

server.listen(3000, () => {
    console.log("服務器啟動啦!");
});

function httpget(cb) {
    // 定義一個存放數據的變量
    let data = "";
    // 因為貓眼的接口是https協(xié)議的,所以我們需要引入https
    // http和https都具有一個get方法能夠發(fā)起get請求,區(qū)別是一個是http協(xié)議,一個是https協(xié)議
    // 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方法獲取的數據是一點點返回的,并不是直接返回全部
            // 監(jiān)聽data,當有數據返回時就會被調用
            res.on("data", (chunk) => {
                // 收集數據
                data += chunk;
            });
            // 監(jiān)聽end,數據返回完畢后調用
            res.on("end", () => {
                cb(data); // 注意這里
            });
        }
    );
}

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

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

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

但在一些情況下,特別是函數多層嵌套調用時(如下面的例子),這種寫法就顯得不夠優(yō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);
}

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

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("服務器啟動啦!");
});

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ā)事件并傳遞數據
                event.emit("resEnd", data);
            });
        }
    );
}

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

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

接口正常使用

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

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

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

關于“怎么使用Node.js的內置模塊event實現(xiàn)發(fā)布訂閱模式”這篇文章的內容就介紹到這里,感謝各位的閱讀!相信大家對“怎么使用Node.js的內置模塊event實現(xiàn)發(fā)布訂閱模式”知識都有一定的了解,大家如果還想學習更多知識,歡迎關注億速云行業(yè)資訊頻道。

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI