質問があるためにここに来ました。クラス コンストラクターを待つにはどうすればよいですか?コンストラクターを非同期にするにはどうすればよいですか?
そして、申し訳ありませんが、文字通りそれはできないというのが答えです。 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 サイトの他の関連記事を参照してください。