一旦你的函数返回(在为它的下一次运行设置超时之后),javascript 将查看下一个需要运行的东西并运行它。
据我所知,javascript 中的“主线程”只是一个响应事件的循环(例如脚本标签的 onload,它运行该标签的内容)。
基于上述两个条件,尽管有任何 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 个调用延迟半秒并检查它们是否交错应该表明工作正常:
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 输出(我不确定),只需将这些字符串推送到数组或字符串中并在运行后检查。您可以在 test 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>);