[解決済み】非同期/待機クラス コンストラクタ
質問
今現在、私は
async/await
をクラスのコンストラクタ関数内で使用します。 これは、カスタム
e-mail
タグを使用しています。
customElements.define('e-mail', class extends HTMLElement {
async constructor() {
super()
let uid = this.getAttribute('data-uid')
let message = await grabUID(uid)
const shadowRoot = this.attachShadow({mode: 'open'})
shadowRoot.innerHTML = `
<div id="email">A random email message has appeared. ${message}</div>
`
}
})
しかし、現時点では、以下のようなエラーが出て、プロジェクトはうまくいきません。
Class constructor may not be an async method
これを回避して、この中でasync/awaitを使えるようにする方法はないでしょうか? コールバックや.then()を必要とする代わりに?
解決方法は?
これは 決して が動作します。
は、その
async
キーワードによって
await
とマークされた関数で使用されます。
async
が、その関数をプロミスジェネレータに変換してくれるのです。ですから
async
はプロミスを返します。一方、コンストラクタは構築中のオブジェクトを返します。このように、オブジェクトとプロミスの両方を返したいという状況は、ありえないことなのです。
async/awaitは基本的にプロミスのためのシンタックスシュガーなので、プロミスが使える場所でしか使うことができません。コンストラクタはプロミスではなく、構築されるオブジェクトを返さなければならないので、コンストラクタでプロミスを使用することはできません。
これを克服するために2つのデザインパターンがありますが、どちらもプロミスが登場する前に考案されたものです。
-
を使用する。
init()
関数を使用します。これは、jQueryの.ready()
. 作成したオブジェクトは、そのオブジェクトの内部でのみ使用できます。init
またはready
関数を使用します。使用方法を説明します。
var myObj = new myClass(); myObj.init(function() { // inside here you can use myObj });
インプリメンテーションです。
class myClass { constructor () { } init (callback) { // do something async and call the callback: callback.bind(this)(); } }
-
ビルダーを使用する。javascriptでこれが使われているのをあまり見たことがありませんが、オブジェクトを非同期に構築する必要がある場合、これはJavaでより一般的な回避策の1つです。もちろん、ビルダーパターンが使われるのは、多くの複雑なパラメータを必要とするオブジェクトを構築するときです。これこそ、非同期ビルダーのユースケースです。違いは、非同期ビルダーはオブジェクトを返すのではなく、そのオブジェクトのプロミスを返すことです。
使用方法
myClass.build().then(function(myObj) { // myObj is returned by the promise, // not by the constructor // or builder }); // with async/await: async function foo () { var myObj = await myClass.build(); }
インプリメンテーションです。
class myClass { constructor (async_param) { if (typeof async_param === 'undefined') { throw new Error('Cannot be called directly'); } } static build () { return doSomeAsyncStuff() .then(function(async_result){ return new myClass(async_result); }); } }
async/awaitを使った実装。
class myClass { constructor (async_param) { if (typeof async_param === 'undefined') { throw new Error('Cannot be called directly'); } } static async build () { var async_result = await doSomeAsyncStuff(); return new myClass(async_result); } }
注意:上記の例では、非同期ビルダーにプロミスを使用していますが、厳密には必要ではありません。コールバックを受け取るビルダーも同様に簡単に書くことができます。
静的関数の内部で関数を呼び出す場合の注意点。
これは非同期コンストラクタとは全く関係なく、キーワードである
this
を必要としない言語から来た人々にとっては、少し驚きかもしれません。
this
というキーワードがあります)。
は、その
this
キーワードは、インスタンス化されたオブジェクトを指します。クラスではありません。したがって、通常
this
なぜなら、スタティック関数はどのオブジェクトにも束縛されず、直接クラスに束縛されるからです。
つまり、次のようなコードで。
class A {
static foo () {}
}
することはできません。
var a = new A();
a.foo() // NOPE!!
として呼び出す必要があります。
A.foo();
したがって、次のようなコードはエラーになります。
class A {
static foo () {
this.bar(); // you are calling this as static
// so bar is undefinned
}
bar () {}
}
これを修正するために
bar
を通常の関数か静的メソッドにすることです。
function bar1 () {}
class A {
static foo () {
bar1(); // this is OK
A.bar2(); // this is OK
}
static bar2 () {}
}
関連
-
[解決済み] JavaScriptで要素のクラスを変更するにはどうすればよいですか?
-
[解決済み] forEachループでasync/awaitを使用する
-
[解決済み] 指定された要素にクラスを追加するには?
-
[解決済み] async」と「await」の使い方とタイミング
-
[解決済み] 非同期アロー関数のシンタックス
-
[解決済み] async/await関数を並列に呼び出す
-
[解決済み] 非同期関数+await+setTimeoutの組合せ
-
[解決済み] 複数のタスクにasync/awaitを使用する
-
[解決済み] トップレベルでasync/awaitを使用するにはどうすればよいですか?
-
[解決済み】Array.mapで非同期awaitを使用する。
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] React with ES7: Uncaught TypeError: Cannot read property 'state' of undefined [duplicate] (未定義のプロパティ'state'を読み込むことはできません。
-
[解決済み】ある要素が可視DOMに存在するかどうかを確認するにはどうすればいいですか?
-
[解決済み] エラー。モジュールhtmlが見つからない
-
[解決済み】Reactのeslintエラーはpropsの検証で見つからない
-
[解決済み】 Uncaught Error: Invariant Violation: 解決済み】 Uncaught Error: Invariant Violation: Element type is invalid: expected a string (for built-in components) or a class/function but got: object.
-
[解決済み】JS ファイルが net::ERR_ABORTED 404 (Not Found) を取得する)
-
[解決済み】XMLパースエラー:ルート要素が見つからない コンソールの場所 FF
-
[解決済み】TypeError: AngularJSで未定義のプロパティ'get'を読み取れない
-
[解決済み] [Solved] Uncaught Invariant Violation: 前のレンダリング中よりも多くのフックをレンダリングする
-
[解決済み】react router v^4.0.0 Uncaught TypeError: 未定義のプロパティ'location'を読み取れない