関数が戻るとすぐに(次の実行のタイムアウトを設定した後)、javascriptは実行が必要な次のことを調べて実行します。
私が知る限り、javascriptの「メインスレッド」は、イベント(そのタグのコンテンツを実行するスクリプトタグのonloadなど)に応答する単なるループです。
上記の2つの条件に基づいて、呼び出しスレッドはsetTimeoutsに関係なく常に完了まで実行され、これらのタイムアウトは呼び出しスレッドに実行するものがなくなった後に開始されます。
これをテストした方法は、a()の呼び出しの直後に次の関数を実行することでした。
function looper(name,duration) {
var start = (new Date()).getTime();
var elapsed = 0;
while (elapsed < duration) {
elapsed = (new Date()).getTime() - start;
console.log(name + ": " + elapsed);
}
}
期間は、a()のsetTimeout期間よりも長い期間に設定する必要があります。期待される出力は、「looper」の出力と、それに続くa()の繰り返し呼び出しの出力になります。
次にテストするのは、a()とその子呼び出しの実行中に他のスクリプトタグを実行できるかどうかです。
あなたはそのようにこれを行うことができます:
<script>
a();
</script>
<script>
looper('delay',500); // ie; less than the 1000 timeout in a();
</script>
<script>
console.log('OK');
</script>
a()とその子がまだ実行されているにもかかわらず、「OK」がログに表示されることを期待します。window.onload()など、これのバリエーションをテストすることもできます。
最後に、他のタイマーイベントも正常に機能することを確認する必要があります。2つの呼び出しを0.5秒遅らせ、それらがインターリーブすることを確認するだけで、正常に機能することが示されます。
function b()
{
console.log("invoked b")
setTimeout(b, 1000);
}
a();
looper('wait',500);
b();
次のような出力を生成する必要があります
invoked
invoked b
invoked
invoked b
invoked
invoked b
それがあなたが探していたものであることを願っています!
Qunitでそれを行う方法に関する技術的な詳細が必要な場合に備えて編集してください:
Qunitがconsole.log出力をキャプチャできない場合(よくわかりません)、それらの文字列を配列または文字列にプッシュして、実行後に確認してください。テストmodule()セットアップでconsole.logをオーバーライドし、ティアダウン時に復元できます。Qunitがどのように機能するかはわかりませんが、「this」を削除し、グローバル変数を使用してold_console_logとtest_outputを格納する必要がある場合があります
// in the setup
this.old_console_log = console.log;
this.test_output = [];
var self = this;
console.log = function(text) { self.test_output.push(text); }
// in the teardown
console.log = this.old_console_log;
最後に、stop()とstart()を利用して、Qunitがテスト内のすべてのイベントの実行が終了するのを待つことを認識できるようにすることができます。
stop();
kickoff_async_test();
setTimeout(function(){
// assertions
start();
},<expected duration of run>);