カテゴリー
【javascript基礎講座】クラスコンストラクタの内部で async/await を使う時の注意
※ 当ページには【広告/PR】を含む場合があります。
2020/06/29
2022/10/03
サードパーティ製のnpmライブラリを利用する際に返り値が
これを自作のクラスのコンストラクタで利用するとなるとひと工夫必要です。
今回はPromiseから返ってくる値でクラスのメンバー変数を初期化するための、ちょっとしたテクニックを解説します。
コンストラクタにasyncは付けられない
まず以下はダメなパターンです。
class HogeClass {
async constructor(hoge) {
// Promiseを返すなんらかのメソッド
this.hogeContent = await initHogeAsync(hoge);
}
}
//...
const hogeInstance = new HogeClass('hoge'); // Error!
このソースコードは通常ビルドエラーとなるか、仮にコンパイルを通過してしてしまったとしても内部エラーで停まります。
これはJavascriptのコンストラクタは通常実体のあるオブジェクトを返す関数である必要があるためです。
一方で
async
Promise
この場合、コンストラクタは
async
...ということは、コンストラクタで
await
という困った場合に使えるテクニックを以降で紹介していきます。
async/awaitの初期化で困った時のFactoryライクなメソッド
先ほどの述べたように、問題は単純で、コンストラクタをasyncな関数にできない、ということでした。
ですのでコンストラクタのようでコンストラクタではない、staticな関数を追加しましょう。
class HogeClass {
// こちらのコンストラクタにはawaitで呼び出ししない
constructor() {}
static async hogeFactorywise(hoge) {
const obj = new Hoge();
// Promiseを返すなんらかのメソッド
obj.hogeContent = await initHogeAsync(hoge);
return obj;
}
}
//...
const hogeInstance = await HogeClass.hogeFacorywise('hoge');
コンストラクタでなければ、
async
コンストラクタを呼び出してインスタンス化したオブジェクトで、Promiseを返すメソッドから値の受け渡しを行うことができるようになります。
応用例 ~ Tensorflowjsのメソッド
以上のようなテクニックを取り上げたのも、Tensorflowjsの関数は主に
Promise<T>
代表的なものだと
公式のAPIリファレンスにもあるように、暗黙としてPromiseを返すので、
await
const model = await tf.loadLayersModel(
'https://storage.googleapis.com/tfjs-models/tfjs/iris_v1/model.json'
);
model.summary();
訓練済みのTensorflowjsの機械学習モデルをクラス変数として持ちたい場合には、コンストラクタでの初期化はできないので、上記のテクニックを利用します。
一例をあげると、AngularのSPAプロジェクト仕立てにしているのでtypescriptコードですが、中身はほぼjavascriptですので、読み替えていただくとして...
import * as tf from '@tensorflow/tfjs';
export class HogeAsyncClass {
config: any;
decodedLayerModel: any;
/**
* staticなfactoryのような関数はconstructorの前に定義することが
* 作法として推奨されいるようなので、この位置でメソッド定義
*/
static async hogeFactorywise(args?: any): Promise<HogeAsyncClass> {
const hogeObj = new HogeAsyncClass(args);
// 👇Promiseから取り出したデータで初期化している
hogeObj.decodedLayerModel = await tf.loadLayersModel('<...モデルを保存した場所までのディレクトリパス>/model.json');
return hogeObj;
}
constructor(args?: any) {
this.config = args.config;
}
}
あとは使う側で、
const hogeInstance = await HogeAsyncClass.hogeFacorywise(<...通常のコンストラクタ引数>);
として扱うことが可能です。
まとめ
Promiseは使い慣れてくると便利です。
これからTensorflowjsを利用したいと思っている方からすると、「これはなんで思うように動かない...?」と感じるかもしれません。
javascriptで機械学習を始める際には、Promiseの挙動はしっかりと押さえておきましょう。
記事を書いた人
ナンデモ系エンジニア
主にAngularでフロントエンド開発することが多いです。 開発環境はLinuxメインで進めているので、シェルコマンドも多用しております。 コツコツとプログラミングするのが好きな人間です。
カテゴリー