Heim > Web-Frontend > js-Tutorial > Wie erstelle ich einen asynchronen Konstruktor in Javascript?

Wie erstelle ich einen asynchronen Konstruktor in Javascript?

Susan Sarandon
Freigeben: 2024-11-24 03:38:10
Original
316 Leute haben es durchsucht

How to make an async constructor in Javascript?

Sie sind hier, weil Sie eine Frage haben: Wie erwarte ich einen Klassenkonstruktor? Wie mache ich den Konstruktor asynchron???

Und die Antwort ist, es tut mir leid, dass Sie es buchstäblich nicht können. Ein Konstruktor für eine Klasse in Javascript muss synchron sein. Es gibt jedoch Implementierungsalternativen, die Ihnen dabei helfen können, das zu erreichen, was Sie wollen. Lass es uns erkunden!

Sie möchten dies wahrscheinlich, weil Sie etwas im Konstruktor initialisieren und es bei jedem Aufruf der Klasse verfügbar haben müssen. Ein gutes Beispiel hierfür wäre, eine Verbindung zu einer Datenbank herzustellen und darauf zu warten, dass diese Verbindung hergestellt wird, bevor Anfragen angenommen werden.

Das Muster dafür ist wirklich einfach! Beginnen wir mit einem Beispiel-Datenbank-Connector unter Verwendung des SQLite-Moduls auf npm:

import sqlite3 from 'sqlite3';
import { open } from 'sqlite';
Nach dem Login kopieren
Nach dem Login kopieren

Um diese Datenbank zu öffnen, müssen Sie auf die Öffnungsfunktion warten. Ich habe meinen freundlichen KI-Code-Helfer gebeten, eine „DBConnector“-Klasse zu entwickeln, und sie hat tatsächlich das allgemeine Muster richtig umgesetzt – das, das Sie überall sehen werden:

class DBConnector {
  constructor() {
    this.db = null;
  }

  async connect() {
    this.db = await open({
      filename: './database.sqlite',
      driver: sqlite3.Database,
    });
  }

  async disconnect() {
    await this.db.close();
  }

  async query(sql, params) {
    return this.db.all(sql, params);
  }
}

// exporting a singleton so there's only one connection
export default new DBConnector();
Nach dem Login kopieren

Sie würden dies einfach aufrufen, indem Sie es importieren und dann auf seine Aufrufe warten:

import db from './dbconnector.js';

await db.connect();
await db.query('GET * FROM test');
Nach dem Login kopieren

Das Problem hier besteht natürlich darin, dass Sie nicht nur manuell myDB.connect() aufrufen müssen, um die Verbindung zu starten, sondern Sie können auch nicht garantieren, dass der Abfrageaufruf funktioniert, beispielsweise wenn Eine andere Datei führt eine Abfrage durch, während Ihre Hauptdatei eine Verbindung herstellt.

Sicher, die Hauptdatei kann auf db.connect(); warten. , aber alles andere, was dieses Modul importiert, hat keine Möglichkeit, dies zu tun. Und Sie denken vielleicht: „Okay, aber ich kannawait db.connect(); auch in anderen Dateien aufrufen, oder?“ und das können Sie... aber dadurch wird jedes Mal wieder eine Verbindung zur Datenbank hergestellt, was je nach verwendetem Gerät langsam sein kann.

Das verzögerte Muster

Das Muster, das ich mir ausgedacht habe, ist etwas komplexer, aber es bleibt einfach und sorgt dafür, dass jedes kleine Stück Code – und Sie selbst – zufrieden sind. Und tatsächlich habe ich es mir selbst ausgedacht, auch wenn es anderen eigentlich bekannt ist. Sie werden „aufgeschobene“ Versprechen genannt.

So funktioniert es.

// still have our imports
import sqlite3 from 'sqlite3';
import { open } from 'sqlite';

// Create the class
class DBConnector {
  // We'll need these private properties:
  #db;
  #defer;
  #resolve;
  #reject;
  // Then we make our constructor:
  constructor() {

    // We create a new promise and store its resolve and reject
    // functions in the class instance properties.
    this.#defer = new Promise((res, rej) => {
      // this is the magic, right here, basically.
      this.#resolve = res;
      this.#reject = rej;
    });

    // So now, this.#defer is a promise! We can await it in other methods.
    // Now we call our this.connect *internally* and automatically.
    this.connect();
  }

  async connect() {
    try {
      this.#db = await open({
        filename: `./database.sqlite`,
        driver: sqlite3.Database,
      });
      // Now that we resolve the promise, any other method that awaits
      // this.#defer will continue executing.
      this.#resolve();
    } catch (err) {
      // in case of error we can of course reject the promise
      // any code using it would then throw an error.
      this.#reject(err);
    }
  }

  async disconnect() {
    // on any action, we just await this.#defer
    await this.#defer;
    await this.#db.close();
  }

  async query(sql, params) {
    // Even in queries, it works perfectly fine!
    await this.#defer;
    // Here we KNOW that this.#db is already initialized.
    return this.#db.all(sql, params);
  }
}

export default new DBConnector();
Nach dem Login kopieren

Ist das nicht ein bezauberndes kleines Muster? Es ist natürlich mehr Code als ein einfaches Beispiel, aber ich persönlich denke, dass es die Messlatte für Boilerplate-Code für Klassen, die hauptsächlich auf asynchronen Methoden basieren, definitiv höher legt.

Mal sehen, wie man es benutzt!

import db from './dbconnector.js';

// it's already initialized... just use it!
await db.query('GET * FROM test');
// and it just works :D 
Nach dem Login kopieren

Bonus: Ich habe eine Bibliothek erstellt!

Ich verwende dieses Muster so oft, dass ich mich am Ende dazu entschieden habe, eine wirklich schnelle und schmutzige Bibliothek zu erstellen und sie auf NPM zu veröffentlichen. Es nennt sich Aufschub und ist ziemlich trivial zu verwenden (es war auch ziemlich trivial zu schreiben, nachdem ich das Muster kannte).

Lassen Sie uns das obige Beispiel neu erstellen und stattdessen Verzögerungen verwenden.

import sqlite3 from 'sqlite3';
import { open } from 'sqlite';
Nach dem Login kopieren
Nach dem Login kopieren

Die Zeichenfolge „db“ ist im Grunde ein beliebiger Zeichenfolgenname, den Sie dem Defer geben möchten, und Sie können so viele erstellen, wie Sie möchten. Natürlich brauchen Sie diese Bibliothek nicht, aber ich persönlich finde sie ganz nett, wissen Sie?

Ich hoffe, Sie haben hier ein wirklich nützliches Muster gelernt, und ich freue mich, heute Teil Ihrer Lernreise gewesen zu sein <3

Das obige ist der detaillierte Inhalt vonWie erstelle ich einen asynchronen Konstruktor in Javascript?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

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
Neueste Artikel des Autors
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage