8

特定のデータを返すコールバック関数を使用する外部スクリプトを読み込んでいます。このデータが受信されない場合、エラーが表示されます。

ここに私が作ったコードがあります:

<script>
//setting initial state so that function will only work once
var visitors_loaded=false;  
var my_callback = function( data ) {
    if (visitors_loaded) return 0;
    if (data) { 
        //success: callback function is called and it has a proper data
    visitors_loaded=true;
    alert(JSON.stringify(data));
    }
    else alert ('error'); //something went wrong
};
</script>
<script onload="my_callback(null)" onerror="my_callback(null)"
src="https://api.clicky.com/api/stats/4?site_id=32020&sitekey=9a19b1a4d1171193&type=visitors&date=this-month&output=json&json_callback=my_callback"></script>

ご覧のとおり...スクリプトには多くの問題が発生する可能性があるため、当然のことながらonerrorイベントを追加しました。この on error イベントは、スクリプトのホスト名またはドメインを存在しないものに変更すると、実際に発生します。

ただし、スクリプトの URL のみを変更した場合でも、サーバーに接続して、代わりにonloadイベントを発生させることができます。これらの無効なリクエストに対してコールバック関数が呼び出されないため、onloadハンドラも追加しました。

問題は、すべてが正常にロードされ、データが返された場合、コールバック関数onloadの両方が起動することです。onloadの前にコールバック関数がトリガーされ、 visitors_loaded変数を設定して、ハンドラー関数が 1 回だけ呼び出されるようにしました。

これまでのところ、JS fiddle と私のオフライン サイトでは完全に動作しますが、これは予想される動作なのだろうか? そのjson_callback関数は常にonloadハンドラの前に優先されますか?

https://jsfiddle.net/5sfk9ht5/4/

4

3 に答える 3

3

その json_callback 関数は常に onload ハンドラの前に優先されますか?

外部スクリプトがmy_callback同期的に呼び出す場合は、はい。

scripting公式のhtml5 仕様のセクションでは、これらがどのように機能するかを説明しています。仕様は非常に一般的であり、エンコーディング、CORS などに関する多くの詳細に対処する必要がありignore-destructive-writes counterます。しかし、この質問では、これらの詳細は気にしません。

ステップ 4 に次の注意事項があります。

注: ここでスクリプトがコンパイルされ、実際に実行されます。

そして、ステップ 7 でloadイベントが発生します。

script 要素で load という名前の単純なイベントを発生させます。

そのため、仕様ではload、スクリプトが実行された後にイベントが常に発生することが定義されています。


onerrorご覧のとおり、この仕様は、URL を変更した場合にイベントが発生しない理由も示しています。イベントは、スクリプトのerrorロードが失敗した場合にのみ作成されます。ただし、すべてのリクエストhttps://api.clicky.com/api/stats/ は HTTP 200 ステータスを返します。無効な URL は XML を返すため、SyntaxError がスローされます。onerrorただし、これによってハンドラーがトリガーされることはありません。


onloadコールバックが非同期的に呼び出された場合、他の人が言及したように、イベントの後にコールバックを呼び出すことができます。しかし、外部スクリプトでこの非同期を実行する理由がわかりません。

于 2016-06-20T13:16:19.147 に答える
2

問題は、すべてが正常にロードされ、データが返された場合、コールバック関数とオンロードの両方が起動することです。onload の前にコールバック関数がトリガーされ、visitors_loaded 変数を設定して、ハンドラー関数が 1 回だけ呼び出されるようにしました。

これは、api.clicky.com から呼び出されたスクリプト内からコールバックが起動されるためです。

これまでのところ、JS fiddle と私のオフライン サイトでは完全に動作しますが、これは予想される動作なのだろうか?

スクリプトが失敗したときに何が起こるかについての関連する質問はこちらにありますが、いくつかのテストを行った結果は次のとおりです。

tester.html:

<script>

var onLoadTest = function() {
    console.log("Onload Called!");
};


var callbacktest = function() {
    console.log("Called from other script!");
};

var errortest = function() {
    console.log("Callback OnError!");
};

</script>

 <script onload="onLoadTest()" onerror="errortest()"
 src="script.js"></script>

script.js:

function otherScriptFunc()
{    
    //call the function in the original script
    callbacktest()
}

otherScriptFunc(); // first call to other script
setTimeout(otherScriptFunc, 0); // final call to other script

コンソール ログの結果

Called from other script!
Onload Called!
Called from other script!
  1. 他の場所の JS の解析が完了すると、あなたOnLoadが呼び出されます (非同期関数は独自の処理を行います)。たとえば、otherScriptFunc();前に呼び出されますonloadsetTimeout(otherScriptFunc, 0);、後に呼び出されますonload

  2. GETOnErrorリクエスト エラーが発生した場合にのみ呼び出されます。IE、ファイルが見つからない、または URL を解決できない - ファイルの内容については何もありません。(私はそれを個別にテストしましたが、ファイル名をいじるだけです)

  3. 他のスクリプトに渡されたコールバックは、他のスクリプトが必要なときにいつでも呼び出すことができます。それはそれへの参照を持っており、しばらくの間それを保持し、遊んだ後に後で呼び出すことができます。つまり、他の場所でデータを待機している非同期呼び出しにある可能性があります。つまり、理論的には、実際には onload をコールバックの前に呼び出すことができますが、それは他のスクリプトに依存しており、それについてできることはあまりありません。

その json_callback 関数は常に onload ハンドラの前に優先されますか?

これは優先順位に関するものではなく、他のスクリプトがいつそれを呼び出すことにしたかに依存するだけです。

于 2016-06-15T02:12:27.073 に答える