Heim  >  Artikel  >  Web-Frontend  >  Das integrierte Modulereignis von Node.js, wie man es zum Implementieren des Veröffentlichungs- und Abonnementmodells verwendet

Das integrierte Modulereignis von Node.js, wie man es zum Implementieren des Veröffentlichungs- und Abonnementmodells verwendet

青灯夜游
青灯夜游nach vorne
2022-09-23 20:11:191445Durchsuche

Jeder muss mit dem Publish and Subscribe-Modell vertraut sein. Es spielt eine große Rolle bei der asynchronen Interaktion und kann unsere Codestruktur klarer, leichter lesbar und einfacher zu warten machen.

Das integrierte Modulereignis von Node.js, wie man es zum Implementieren des Veröffentlichungs- und Abonnementmodells verwendet

In nodenode中我们可以使用 内置模块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");

运行结果:

Das integrierte Modulereignis von Node.js, wie man es zum Implementieren des Veröffentlichungs- und Abonnementmodells verwendet

❗️ 事件重复监听的问题

==注意:当同一事件被监听多次时,触发事件时会同时触发这个事件的所有事件处理函数==

Das integrierte Modulereignis von Node.js, wie man es zum Implementieren des Veröffentlichungs- und Abonnementmodells verwendet

二、应用

在上一节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接口:

Das integrierte Modulereignis von Node.js, wie man es zum Implementieren des Veröffentlichungs- und Abonnementmodells verwendet

接口正常使用

注意上边代码new EventEmitter()的位置,如果new EventEmitter()是在外部的话,相当于是只有一个全局的event对象,当我们每次调用/api/maoyan接口时,node都会监听一个新的resEnd事件,这就会导致resEnd事件被重复监听

Das integrierte Modulereignis von Node.js, wie man es zum Implementieren des Veröffentlichungs- und Abonnementmodells verwendet

所以我们才需要将创建event对象的代码new EventEmitter()写到接口的case分支里,这样当我们调用这个接口时,会创建一个新的event对象,老的event对象被弃用会被JS垃圾处理机制给处理掉,这样就不会出现resEnd können wir das

eingebaute Modul event

verwenden, um das Publish-Subscribe-Modell zu implementieren über event und demonstrieren Sie seine Rolle in unserer tatsächlichen Entwicklung, fangen wir an! [Verwandte Tutorial-Empfehlungen: nodejs-Video-Tutorial]

🎜1. Erstmalige Verwendung🎜

🎜🎜Einführung in das integrierte Event-Modul🎜 span>🎜 rrreee🎜🎜Ereignisobjekt erstellen🎜🎜
🎜eventDas integrierte Modul ist im Wesentlichen ein Konstruktor. Wir müssen den new-Operator übergeben, um ihn aufzurufen >event Verwenden Sie die Funktion on für das Objekt, um ein Listening-Ereignis zu definieren. Die Syntax lautet: event.on(event name, event processing function)🎜rrreee 🎜🎜Ereignisse auslösen🎜🎜🎜Verwenden Sie die Emit-Funktion für das event-Objekt, um das überwachte Ereignis auszulösen. Die Syntax lautet: event.emit (der Name des Ereignisses, das ausgelöst werden muss, Parameter, die an die Ereignisverarbeitungsfunktion übergeben werden müssen)🎜rrreee🎜 🎜Vollständiger Code🎜🎜rrreee🎜🎜Laufende Ergebnisse: 🎜🎜🎜Das integrierte Modulereignis von Node.js, wie man es zum Implementieren des Veröffentlichungs- und Abonnementmodells verwendet🎜🎜🎜❗️ Problem mit wiederholter Ereignisüberwachung🎜🎜🎜==Hinweis: Beim gleichen Ereignis wird mehrmals überwacht. Wenn das Ereignis ausgelöst wird, werden alle Ereignishandler dieses Ereignisses gleichzeitig ausgelöst == 🎜🎜Das integrierte Modulereignis von Node.js, wie man es zum Implementieren des Veröffentlichungs- und Abonnementmodells verwendet🎜

🎜2. Bewerbung🎜

🎜Im vorherigen AbschnittNode.js | Erstellen eines Back-End-Servers (einschließlich der Verwendung integrierter Module http | url |. querystring) 🎜Es gibt eine Methode, die node verwendet, um get-Anfragen zu simulieren (Weiterleitung domänenübergreifender Daten): 🎜rrreee🎜Achten Sie auf die Zeilen 19 und 49 des obiger Code: 🎜rrreeerrreee🎜In diesem Beispiel erhalten wir httpget übergeben. Es gibt eigentlich kein Problem mit dieser Art, die von der Funktion >httpget erhaltenen Daten zu schreiben. code>-Funktion und wird häufig in der Entwicklung verwendet. 🎜🎜Aber in einigen Fällen, insbesondere bei 🎜mehrstufigen verschachtelten Funktionsaufrufen🎜 (wie im folgenden Beispiel), scheint diese Schreibweise nicht elegant genug zu sein, da die Codestruktur nicht sehr klar ist und nicht intuitiv verstanden werden kann : 🎜rrreee🎜Lassen Sie uns das integrierte Modul event verwenden, um den obigen Fall von node zu transformieren, der eine get-Anfrage simuliert (Weiterleitung domänenübergreifender Daten). ): 🎜 rrreee🎜Führen Sie die /api/maoyan-Schnittstelle aus und rufen Sie sie auf: 🎜🎜Das integrierte Modulereignis von Node.js, wie man es zum Implementieren des Veröffentlichungs- und Abonnementmodells verwendet🎜
🎜Die Schnittstelle wird normal verwendet🎜
🎜🎜Achten Sie auf die Position des obigen Codes new EventEmitter ()🎜, wenn new EventEmitter() extern ist, ist es gleichbedeutend mit nur einem globalen event-Objekt. Jedes Mal, wenn wir den aufrufen /api/maoyan-Schnittstelle, node hört auf ein neues resEnd-Ereignis, was dazu führt, dass das resEnd-Ereignis wiederholt überwacht wird 🎜: 🎜🎜Das integrierte Modulereignis von Node.js, wie man es zum Implementieren des Veröffentlichungs- und Abonnementmodells verwendet🎜 🎜Also müssen wir erstellen. Der Code des Ereignisses-Objekts new EventEmitter() wird in den case-Zweig der Schnittstelle geschrieben, damit wann Wenn wir diese Schnittstelle aufrufen, wird ein neues event-Objekt erstellt. Wenn das alte event-Objekt veraltet ist, wird es von JS verworfen Müllentsorgungsmechanismus, sodass resEnd nicht angezeigt wird. >Das Problem der wiederholten Überwachung von Ereignissen🎜🎜Weitere Informationen zu Knoten finden Sie unter: 🎜nodejs-Tutorial🎜! 🎜

Das obige ist der detaillierte Inhalt vonDas integrierte Modulereignis von Node.js, wie man es zum Implementieren des Veröffentlichungs- und Abonnementmodells verwendet. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:juejin.cn. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen