質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.41%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

1回答

668閲覧

動的に読み込むJavaScriptの実行が完了したタイミングで処理をしたい

gosaro

総合スコア24

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

0クリップ

投稿2023/02/07 01:36

前提

他の方による次の質問の回答を参考にしています。
「外部からjsで動的にCDNからjsファイルを読み込む方法について」
https://teratail.com/questions/pi49k2t5q4p48y

仕様上の都合により、PHPなどのサーバーサイドの処理を使わず、JavaScriptで完結したいです。(jQuery等を使うのは構いません)

発生している問題・エラーメッセージ

(index):13 Uncaught (in promise) ReferenceError: message is not defined at (index):13:15

該当のソースコード

release.js

1const message = 'release mode'

debug.js

1const message = 'debug mode'

index.html

1<script> 2window.addEventListener('load',async()=>{ 3 const mode = 'debug' 4 let src = 'release.js'; 5 if (mode == 'debug') { 6 src = 'debug.js' 7 } 8 const script=Object.assign(document.createElement('script'),{ 9 src:window.URL.createObjectURL(new Blob([await fetch(src).then(res=>res.text())])) 10 }); 11 document.head.insertBefore(script,document.head.querySelector('script')); 12 //await (async (ms) => new Promise(resolve => setTimeout(resolve, ms)))(1000) 13 console.log(message) // ここでエラーが発生 14}); 15</script> 16<button onclick="console.log(message)">click</button>

試したこと

1.ボタンをクリックする。
2.console.log() の上のコメントを解除して1秒待つ。

どちらでも「debug mode」と正常に出力されるので、読み込むJavaScriptが実行される前にconsole.log()が実行されるのが原因だと思われます。

ボタンクリックのようにユーザーの操作を待つのは論外として、動的に読み込みたいJavaScriptが多数あるため一定時間待つ方法も避けたいです。

補足情報(FW/ツールのバージョンなど)

Windows10 Pro
Chrome 108.0.5359.126

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

m.ts10806

2023/02/07 01:39

必ず利用する変数名なら、いっそ呼び出し元のグローバル変数として定義しておくなど回避は可能かもしれませんが、非同期になっていることも一端ではないかなと。 > async() 手書きとかで良いのでいったん流れを整理されたほうが良いかもしれません(あくまで確認のためこちらでコメントしました)
gosaro

2023/02/07 01:57

早速のコメントありがとうございます。 グローバル変数というのは上記の例だと message のことでしょうか。 グローバル変数にして適当な初期値を設定しておけば message is not defined は回避することができますが、期待している 'debug message' は出力されません。 また、イベントリスナは非同期ですが、リスナ内の処理は同期的に行っているので、関係ないはずです。
m.ts10806

2023/02/07 02:59

了解です 処理の全体像が見えなかったための確認でした
guest

回答1

0

ベストアンサー

javascript

1window.addEventListener('DOMContentLoaded',async()=>{ 2 const mode = 'debug'; 3 let src = 'release.js'; 4 if (mode == 'debug') { 5 src = 'debug.js'; 6 } 7 const script=Object.assign(document.createElement('script'),{src}); 8 document.head.appendChild(script); 9 await new Promise(resolve=>{ 10 script.addEventListener('load',resolve); 11 }); 12 console.log(message); 13});

投稿2023/02/07 02:40

yambejp

総合スコア115568

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

gosaro

2023/02/07 02:48

できました。ありがとうございました。
gosaro

2023/02/07 03:33

万一リスナを仕掛ける前にロードが完了してしまうとawaitで止まってしまうと思いますので、念のため次のようにしようと思います。 : const script=Object.assign(document.createElement('script'),{src}); const promise = new Promise(resolve=>{ script.addEventListener('load',resolve); }); document.head.appendChild(script); await promise; console.log(message);
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.41%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問