浏览器JavaScript:setTimeout和主程序

4
当在浏览器中运行时,setTimeout是否会在主程序执行完成之前触发其代码?主要的浏览器供应商是否就此行为达成了共识,还是这只是实现的副作用?(或者他们已经同意将这个副作用保留为标准行为)
考虑一个非常简单(但无用)的程序。
setTimeout(function(){
    console.log("Timeout Called")
},1);
for(var i=0;i<10000000;i++){};
console.log("done");

首先我们设置了一个单独的微秒级别的setTimeout回调函数,它将输出Timeout Called到控制台。

然后我们在循环中旋转超过一个微秒的时间。

然后我们在控制台输出done

当我运行这个程序时,它总是输出

done
Timeout Called

那就是说,只有在主程序运行完后,setTimeout回调函数才会被执行。这是可靠且定义明确的行为吗?还是有时候会先暂停主程序的执行,然后运行回调函数,最后再继续执行主程序呢?

1
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/EventLoop - zzzzBov
3个回答

3

是的,这是定义行为。一种常见的误解是Ajax回调在某个时间不确定地执行,可能在当前执行路径完成之前,而实际上它们总是在某个时间之后执行。

Javascript是单线程的,并且在当前线程完全执行完成之前,永远不会返回到事件循环。

异步函数(例如事件处理程序(包括Ajax)或使用setInterval/setTimeout安排的函数)永远不会在当前执行路径完成之前执行。


2
除了浏览器的错误外。Safari 5 有一个错误一段时间会触发来自嵌套 iframes 的“load”事件,并且这些事件将抢占运行事件处理程序。 - Pointy
@Pointy,我不知道那个错误。谢谢你指出来。你有一个参考链接可以添加到我的答案吗? - Paul
1
嗯,我只知道这是因为它对jQuery产生了一些极其奇怪的行为。我会看看能否找到我之前记录的那个bug。我认为这真的不值得担心;毕竟,由于Chrome每隔3个小时就会更新一次,任何事情随时都可能发生 :) - Pointy
2
这是票证。感觉像是昨天的事,但已经过去将近3年了!(http://bugs.jquery.com/ticket/7344) - Pointy

2

这是非常明确定义的行为。

浏览器是同步的,在执行下一个操作之前仍然需要等待前一个操作完成。


1
使用timeOut时,它会先等待您传递的毫秒数,然后继续等待,直到代码中有一个空闲位置。通常,这意味着它会等到代码完成。唯一的例外(有点)是在使用其他timeOutsetInterval时。例如,如果您的循环已经结束了。
for(var i=0;i<10000000;i++){
    setTimeout(function () {
        console.log('One iteration');
    }, 15);

};

你的输出将会是:
done
Timeout Called
One iteration
One iteration

等等。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接