はじめに
ダイナミックimportのメリットを確かめているところです。
クラスファイルをダイナミックimportしようとサンプルを作成して確かめています。一つのクラスファイルに複数のクラスを定義して、それぞれにexportするクラスとexportしないクラスを作り、ダイナミックimportでクラスのロード状況をチェックしました。すると、exportするしないにかかわらず、すべてのクラスがロードされていました。
当初思っていたことと違っていました。てっきり、exportしないクラスはロードされないものと思っていました。
このように、ダイナミックimportと言っても、仕様を思い違いしているケースは多いと思います。
ダイナミックimportのうたい文句は、必要のあるモジュールのみをロードするとありますので、そうなると思っていました。
デバッグしているページ(サンプル)
ではどうすればいいのか
一つのクラスファイルに何でもかんでも入れるのではなく、機能を分けてそれぞれのクラスファイルにすれば、選択的ダイナミックimportができるようになります。
その場合は、import("クラスAフィル");import("クラスBフィル");import("クラスXフィル");というようにすればいいはずです。
必要なクラスファイルだけ、ダイナミックimport()します。
exportしていないクラスファイルをダイナミックimportするとエラーになります。
//
export class AAA{
aaa(){
alert("メソッドaaa()コール。");
}
bbb(){
alert("メソッドbbb()コール。");
}
}
//
class BBB{
aaa(){
alert("メソッドaaa()コール。");
}
bbb(){
alert("メソッドbbb()コール。");
}
}
//
import("./aaa.js");
よくあるエラーは
'undefined'エラーはよく発生しますが、これが中々、くせものです。
あるオブジェクトのプロパティを参照するところで、そのオブジェクト自体がまだ、未設定のまま、そこのあるプロパティを参照しようとしているケースです。これが、中々、気づきません。
デバック中に、結構、不用意に、オブジェクトの設定個所を移動していたりしています。その時に、プロパティの参照個所までは変更しないまま、テストを続けているとundefinedエラーが発生してしまいます。迂闊と言えば迂闊です。その時、すぐに気が付けばいいのですが、これが、デバッグを焦っていると中々、気づけません。
早く改修しなければというプレッシャーがより、解決を遅らせています。
こういう時こそ、落ち着いて、原因の解明に努めなければいけません。これは、知識があるないには関係ありません。
よくある不具合の現象は
これもデバックをしているとよく、出会います。それは、ページを新たにタブに初期状態で表示させたときです。必要な要素が表示されていないのです。仕方がなく、リロードしてみます。すると表示されます。このように、何回かリロードしてみると表示されますが、初回は表示されないという現象です。
これも、突き詰めて調べて行くと、その時点で必要なオブジェクトがundefinedになっていたということがわかります。
原因はわかりましたが、それでは、どこで、どのタイミングで、そのオブジェクトにデータを設定したらいいのかを見極めることが簡単ではありません。
その実行タイミング、場所を見つけるのが結構、難しいです。
ダイナミックimportを使用していると、これが関係してきます。
これのヒットのサンプルコードを以下に示します。
修正前
/*****************************************************************
*初期化
*ページをロード後にコール
*
******************************************************************/
window.addEventListener('load', function () {
//ここで、auto_start()を実行するには、条件があり、必ず、先にglistobjが生成されていなければならない。さもないとundefinedエラーになる。
auto_start("8ODcuS8bUuc"); //河内おとこ節
});
これは、不用意にも、glistobjオブジェクトを初期化していない状態で、それを使用している、auto_start(....)をコールしていました。
修正後
以下は、@junerさんのコメントを採用させていただきました。
const moduleWait = import('./favoriteClass.js');
/*****************************************************************
*初期化
*ページをロード後にコール
*
******************************************************************/
window.addEventListener('load', async function () {
console.log("no.7 ");
//ここでは、まだ実行するのは、早い。glistobjがないため。
const {commentInput,List} = await moduleWait;
console.log("no.6 ");
//これはテストで、クラスAAAをexportしている。
gtestobj = new commentInput("これはテストです。");
//window.gtestobj = gtestobj;
// 動的に読み込まれたListクラス
//export指定
glistobj = new List("ランダムリスト");
//ここで、auto_start()を実行するには、条件があり、必ず、先にglistobjが生成されていなければ
//ならない。さもないとundefinedエラーになる。
auto_start("8ODcuS8bUuc"); //河内おとこ節
});
上は、しっかり、glistobjオブジェクトをセットしてから、auto_start(...)をコールしています。これで、不具合はなくなりました。
あとがき
デバッグしていて、難しいのは、やはり、上述のような不具合です。
デバックしていて気持ちがいいのは、ページをリクエストして、一発目で、必要な画面が表示され、同時に、各操作がスムーズに進んでゆくことです。エラーの発生がなく、何度繰り返しても正常に動作することです。
正常な処理は、あたり前ですが、処理の実行前に正しいデータが事前にセットされていることです。この当たり前のことが、デバッグ中は、特に慌てているときは、できていないために発生します。今回の教訓は、ダイナミックimportで、どのタイミングで、どの場所でファイルを読んで、初期設定をしたらいいのかを見極めることでした。