Heim > Web-Frontend > js-Tutorial > Hauptteil

So verarbeiten Sie Socket.io-Ereignisse einfach der Reihe nach: eine Kurzanleitung

王林
Freigeben: 2024-08-14 00:00:03
Original
689 Leute haben es durchsucht

How to Simply Handle Socket.io Events in Sequence: a Short Guide

Alle eingehenden Socketio-Ereignisse werden in der Reihenfolge ihres Eintreffens verarbeitet. Diejenigen mit synchronen Handlerfunktionen beenden die Verarbeitung garantiert in derselben Reihenfolge. Bei Ereignissen mit asynchronen Handlern ist dies jedoch möglicherweise nicht der Fall, da die Verarbeitung in beliebiger Reihenfolge abgeschlossen werden kann. Dieses Verhalten macht unseren Code schneller, ist aber in manchen Fällen möglicherweise nicht das, was wir wollen.

In diesem kurzen Beitrag erfahren Sie, wie Sie Ereignisse mit asynchronen Aufgaben in der Reihenfolge ihres Eintreffens auf dem Server starten und verarbeiten lassen. Um dies zu erreichen, erstellen wir ein einfaches benutzerdefiniertes Warteschlangensystem.

Lass uns eintauchen.

Das Problem

Angenommen, Sie haben eine Situation, in der zwei Clients mit Ihrem Socketio-Server verbunden sind. Sie möchten ein Verhalten, bei dem der erste, der ein Ereignis sendet, eine neue Zeile in einer Datenbanktabelle erstellt und der zweite dieselbe Zeile aktualisiert. Ihr Code könnte etwa so aussehen:

io.on("connection", (socket) => {
    console.log("A user connected");

    socket.on("SOME_EVENT", async(param) => {
            //check whether the column already exists:
            const column = await db.select...

            //if column exists, update it:
            if(column){
                await db.update...
            }

            //else, create one
            await db.insert...
    })
}
Nach dem Login kopieren

Das Problem besteht nun darin, dass, wenn die beiden Clients gleichzeitig „SOME_EVENT“ ausgeben, die Möglichkeit besteht, dass sie beide eine neue Zeile in der Datenbank erstellen, was nicht das ist, was wir wollen.

Lösung des Problems mit einem Warteschlangensystem

Anstatt socketio die Ausführung der Handler-Funktionen zu erlauben, fangen wir sie ab und entscheiden, wann sie ausgeführt werden. Wenn wir die Handler abfangen, senden wir sie an unser Warteschlangensystem, das für die ordnungsgemäße Implementierung verantwortlich ist.

Das System wird aus zwei Hauptkomponenten bestehen – einer Warteschlange und einer Ereignisschleife.

Was ist eine Warteschlange?

In der Informatik ist eine Warteschlange eine Datenstruktur, die es uns ermöglicht, Daten sequentiell zu speichern und zu verwalten. Um dies zu erreichen, erlaubt die Struktur nur das Hinzufügen von Daten an einem Ende (dem Schwanz) und die Ausgabe am anderen Ende (dem Kopf). Diese Eigenschaft wird im Volksmund FIFO genannt, was soviel bedeutet wie „first in first out“.

Warteschlange ist ein abstrakter Datentyp (ADT). Wie andere ADTs verfügen viele Programmiersprachen, einschließlich Javascript, nicht standardmäßig über es. In diesem Beitrag modellieren wir unsere Warteschlange mithilfe der Unshift- und Pop-Methoden des Javascript-Arrays.

Was ist eine Ereignisschleife?

Im Großen und Ganzen ist eine Ereignisschleife ein Konstrukt, das in Intervallen ausgeführt wird und Aufgaben unter bestimmten Bedingungen ausführt. In unserem Fall verwenden wir ein setInterval, das ständig prüft, ob die Warteschlange ausstehende Funktionen enthält, und die nächste Funktion erst aufruft, wenn die vorherige abgeschlossen ist.

Implementierung des Warteschlangensystems

class QueuingSystem {
    //We're making the queue private so that it can only be 
    //modified only within the class
    #queue = [];
    constructor(interval) {
        this.interval = interval;
    }

    //returns last item of an array:
    lastItem(arr) {
        return arr[arr.length - 1];
    }

    //returns true if array is empty:
    isEmpty(arr) {
        return arr.length == 0;
    }

    //responsible for executing the function at the head of the queue:
    async run(arr) {
        //removing the function at the head of the queue:
        const func = arr.pop();

        //adding "false" placeholder at the head to indicate that 
        //a function is being executed:
        arr.push(false);

        //executing the function:
        await func();

        //removing the false placeholder at the head to indicate that 
        //the run function is ready to execute the next function: 
        arr.pop();
    }

    //function to add to the tail end of the queue:
    addToQueue(func) {
        this.#queue.unshift(func);
    }

    //function to start the event loop:
    start() {
        return setInterval(() => {
            //checking if the run method is free by checking if the item at the head is false.
            //and checking if the array isn't empty
            if (this.lastItem(this.#queue) !== false 
            && !this.isEmpty(this.#queue)) {
                this.run(this.#queue);
            }
        }, this.interval);
    }

    //stopping the event loop if no longer needed:
    stop() {
        clearInterval(this.start());
    }
}
Nach dem Login kopieren

Unsere Nachrichtenwarteschlangenklasse ist jetzt bereit, Funktionen nacheinander zu empfangen und auszuführen.

Verwendung unseres Systems in Socket.io

Sobald unser Warteschlangensystem eingerichtet ist, verwenden wir es in unserem Code:

//Create a socketQueue that loops after every half of a second:
const socketQueue = new QueuingSystem(500)

io.on("connection", (socket) => {
    console.log("A user connected");

    const handler = async(param) => {
            //check whether the column already exists:
            const column = await db.select...

            //if column exists, update it:
            if(column){
                await db.update...
            }

            //else, create one
            await db.insert...
    }

    socket.on("SOME_EVENT", (param) => {
        //Add the handler function to socketQueue queue
        socketQueue.addToQueue(hanlder.bind(null, param))
    })
}

server.listen(PORT, () => {
    //start the queuing system:
    socketQueue.start();
    console.log("App listening on port", PORT);
});
Nach dem Login kopieren

Die Bind-Methode in Javascript wird verwendet, um Funktionen zusammen mit ihren Parametern an Objekte anzuhängen, diese jedoch nicht aufzurufen. In unserem Fall hängen wir die Funktion keinem Objekt an, deshalb ist das erste Argument null.

Abschluss

Die von uns erstellte Nachrichtenwarteschlangenklasse kann uns dabei helfen, Ereignisse mit asynchronen Handlern sequentiell auszuführen. Wenn Sie ein komplexeres Warteschlangensystem benötigen, schauen Sie sich BullMQ oder andere robuste Lösungen an. Viel Spaß beim Codieren!

Das obige ist der detaillierte Inhalt vonSo verarbeiten Sie Socket.io-Ereignisse einfach der Reihe nach: eine Kurzanleitung. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Quelle:dev.to
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage
Über uns Haftungsausschluss Sitemap
Chinesische PHP-Website:Online-PHP-Schulung für das Gemeinwohl,Helfen Sie PHP-Lernenden, sich schnell weiterzuentwickeln!