Javascriptで非同期コンストラクターを作成するにはどうすればよいですか?

Susan Sarandon
リリース: 2024-11-24 03:38:10
オリジナル
232 人が閲覧しました

How to make an async constructor in Javascript?

質問があるためにここに来ました。クラス コンストラクターを待つにはどうすればよいですか?コンストラクターを非同期にするにはどうすればよいですか?

そして、申し訳ありませんが、文字通りそれはできないというのが答えです。 Javascript のクラスのコンストラクターは同期的である必要があります必要があります。ただし、実装には、必要なことを行うのに役立つ代替手段があります。探検してみましょう!

コンストラクターで何かを初期化し、クラスへの呼び出しで使用できるようにする必要があるため、おそらくこれが必要になります。この良い例は、データベースに接続し、クエリを受け入れる前にその接続が確立されるのを待つことです。

このパターンはとても簡単です。 npm:
の sqlite モジュールを使用して、データベース コネクタの例から始めましょう。

import sqlite3 from 'sqlite3';
import { open } from 'sqlite';
ログイン後にコピー
ログイン後にコピー

このデータベースを開くには、open 関数を待つ必要があります。私はフレンドリーな AI コード ヘルパーに「DBConnector」クラスを考え出すように依頼しました。そして、それは実際に一般的なパターンを正しく実現しました - どこにでも見られるパターンです:

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();
ログイン後にコピー

これをインポートして呼び出しを待つだけでこれを呼び出すことができます。

import db from './dbconnector.js';

await db.connect();
await db.query('GET * FROM test');
ログイン後にコピー

ここでの問題は、もちろん、接続を開始するために手動で myDB.connect() を呼び出す必要があるだけでなく、クエリ呼び出しが機能するかどうかも保証できないことです。メインファイルが接続しているときに、別のファイルがクエリを実行します。

確かに、メインファイルは db.connect() を待つことができます。ただし、このモジュールをインポートする他のものにはそれを行う方法がありません。そして、「わかりましたが、他のファイルでも await db.connect(); を呼び出すことができますよね?」と思うかもしれません。そしてそれは可能です...しかし、毎回データベースに再接続することになり、使用しているものによっては遅くなる可能性があります。

遅延パターン

私が思いついたパターンはもう少し複雑ですが、シンプルなままで、コードのすべての部分、そしてあなた自身がすべて満足できるようにします。そして実際には他の人に知られているものであっても、実際には私がそれを自分で考え出しました。これらは「遅延」約束と呼ばれます。

その仕組みは次のとおりです。

// 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();
ログイン後にコピー

それは魅力的な小さなパターンではないでしょうか?もちろん、これは基本的な例というよりも多くのコードですが、個人的には、主に非同期メソッドに基づくクラスの定型コードの基準を確実に引き上げていると思います。

使い方を見てみましょう!

import db from './dbconnector.js';

// it's already initialized... just use it!
await db.query('GET * FROM test');
// and it just works :D 
ログイン後にコピー

おまけ:図書館を作りました!

私はこのパターンを頻繁に使用しているので、最終的には非常に簡単で汚いライブラリを作成し、NPM で公開することにしました。これは延期と呼ばれるもので、使い方は非常に簡単です (パターンを知ってしまえば、書くのも非常に簡単でした)。

代わりに延期を使用して上記の例を作り直してみましょう。

import sqlite3 from 'sqlite3';
import { open } from 'sqlite';
ログイン後にコピー
ログイン後にコピー

「db」文字列は基本的に、遅延に付ける任意の文字列名であり、好きなだけ作成できます。明らかに、このライブラリは必要ではありませんが、個人的には非常に素晴らしいと思います。

ここで本当に役立つパターンを学んでいただければ幸いです。今日の学習の旅に参加できてうれしいです

以上がJavascriptで非同期コンストラクターを作成するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:dev.to
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート