同期XMLHttpRequestのような同期方法でjavascriptファイルをロードして実行する方法はありますか?
私は現在、同期XMLHttpRequestを使用しており、これを評価していますが、そのコードのデバッグは非常に困難です...
ご協力いただきありがとうございます!
更新
私は今これを試しました:
test.html
<html>
<head>
<script type="text/javascript">
var s = document.createElement("script");
s.setAttribute("src","script.js");
document.head.appendChild(s);
console.log("done");
</script>
</head>
<body>
</body>
</html>
script.js
console.log("Hi");
出力:こんにちは
そのため、同期的に実行されませんでした。 「こんにちは」を最初に表示するアイデアはありますか?
更新2その他の例
test.html(スクリプトタグ内のコード)
var s = document.createElement("script");
s.setAttribute("src","script.js");
document.head.appendChild(s);
SayHi();
script.js
function SayHi(){
console.log("hi");
}
出力:キャッチされていないReferenceError:SayHiは定義されていません
これを使用する場合:
function loadScriptSync (src) {
var s = document.createElement('script');
s.src = src;
s.type = "text/javascript";
s.async = false; // <-- this is important
document.getElementsByTagName('head')[0].appendChild(s);
}
必要なことを実行できます(ただし、追加のスクリプトファイルに分割されます)
test.html(スクリプトタグ内のコード):
loadScriptSync("script.js");
loadScriptSync("sayhi.js"); // you have to put the invocation into another script file
script.js:
function SayHi() {
console.log("hi");
}
sayhi.js:
SayHi();
DOMの準備が整った後に読み込まれるすべてのスクリプトは、非同期で読み込まれます。ブラウザがそれらを同期的にロードする唯一の理由は、何かを出力できる関数write
です。したがって、スクリプト要素のonloadコールバックを使用して、目的を達成できます。
var s = document.createElement("script");
s.setAttribute("src","script.js");
s.onload = function(){
console.log('Done');
}
document.head.appendChild(s);
別の方法は、XHRを介してjsファイルをロードし、script要素内にコードを設定することです。
window.onload = function(){
var req = new XMLHttpRequest();
req.open('GET', "test.js", false);
req.onreadystatechange = function(){
if (req.readyState == 4) {
var s = document.createElement("script");
s.appendChild(document.createTextNode(req.responseText));
document.head.appendChild(s);
}
};
req.send(null);
}
同様の質問から( https://stackoverflow.com/a/3292763/235179 ):
_<script type="text/javascript">
document.write('<script type="text/javascript" src="other.js"><\/script>');
</script>
<script type="text/javascript">
functionFromOther();
</script>
_
_document.write
_ 'dスクリプトから呼び出されるコードは、独自の_<script>
_にあるか、window.onload()
イベントにある必要があります。
あなたのコードをまとめると:
1. create script element
2. set its attribute src
3. set its attribute deferred
4. display done...
この最初の部分は実行を停止し、次のスクリプトに引き渡します
5. script executes and displays Hi
すべてが非常に同期しています... Javascriptでは、最後の行まで実行されるか、内部システム(XHRやタイマーなど)に実行を渡すまで、一部のコードが完全に実行されます。
後で実行するためにいくつかのパーツを準備したいときは、setTimeout
で準備します。タイムアウトが他のコードよりも短い場合でも、実行にかかる時間です。コードの実行が完了した後。例:
// some code
setTimeout(function(){ alert("I'm second alert"); }, 1);
longExecutionTask();
alert("I'm the first alert");
上記のコードでは、setTimeout
が1ミリ秒後に実行するように設定されている場合でも、alert
ボックスの表示で終了する実行終了後のコードまでは開始されません。同じことがあなたの場合にも起こります。コードの最初のバッチは、他の何かを開始する前に実行を終了する必要があります。
私が答えを書いた後、さらにコードを追加したので、ここで詳細を説明します。
スクリプトタグを追加しても、すぐには実行されません。 HTMLパーサーが追加したSCRIPT
要素に到達すると、スクリプトの読み込みと実行が発生します。その時点でそれをロードし、そのコンテンツを評価/実行します。
HEAD
が解析され、そのSCRIPT
子タグが解析および実行されます。この実行により、まだ解析されていないBODY
タグにもう1つの要素が追加されます。BODY
に進み、そのコンテンツ(新しく追加されたSCRIPT
タグ)を解析し、スクリプトをロードしてそのコンテンツを実行します。SCRIPT
要素は、ページが解析され、ブラウザで既にレンダリングされた後に追加された場合にのみすぐに実行されます。あなたの場合、そうではありません。最初のスクリプトはすぐに実行され、解析が行われると動的に追加されたスクリプトが実行されます。
それらの間で非同期操作を同期できます。ループを表す再帰関数を作成し、前の終了時に次の操作を呼び出します。次の関数は、同様の手法でスクリプトを順番にインポートします。スクリプトがロードされるのを待機し、エラーがない場合は次へ続行します。エラーが発生した場合、エラーイベントでコールバック関数を呼び出し、エラーがない場合は、すべてのスクリプトがロードされた後、同じコールバック関数をnullで呼び出します。また、s.parentNode.removeChild(s)
を使用して自動的にクリーンアップします。
function importScripts(scripts, callback) {
if (scripts.length === 0) {
if (callback !== undefined) {
callback(null);
}
return;
}
var i = 0, s, r, e, l;
e = function(event) {
s.parentNode.removeChild(s);
if (callback !== undefined) {
callback(event);
}
};
l = function() {
s.parentNode.removeChild(s);
i++;
if (i < scripts.length) {
r();
return;
}
if (callback !== undefined) {
callback(null);
}
};
r = function() {
s = document.createElement("script");
s.src = scripts[i];
s.onerror = e;
s.onload = l;
document.head.appendChild(s);
};
r();
}