为什么在 Firefox 上 "click" 事件循环完成之前会触发超时?
Why does the timeout fire before the "click" event loop is complete on Firefox?
步骤:
- 运行 Firefox 中的代码
- 等待 5 秒(重要!)
- 按确定或取消
- 期望标志 == 0,但它是 10。
var flag;
function myFunction(){
flag = 0
console.info("initial", flag);
setTimeout(function(){
flag = 10;
}, 200);
confirm("conf");
alert("should be 0: "+flag);
}
document.getElementById('button').onclick=myFunction;
<button type="button" id="button">Click Me!</button>
什么?您 将 标志设置为 10。为什么您希望它为 0?
因为与许多浏览器不同,Firefox 可能 允许 JavaScript 线程 运行 其他代码,而 alert
、prompt
,并且显示 confirm
模态,暂停 current 代码。 (有关该句子中 "may" 的更多信息,请参阅答案结尾。)调用 alert
等的任务已暂停,因此该任务中的代码不会继续,但 其他 任务允许运行。
这意味着
计时器可以获得回调
Ajax 完成处理程序可以 运行
等
从来没有JavaScript运行宁并发在两个地方,但Firefox确实让线程运行其他任务,而一个任务是被那些模态暂停。
这是 Firefox 的一个怪癖。我首先是在 Stack Overflow 上了解到它的,thanks to bobince。
为什么我说 "may" 允许 JavaScript 线程 运行:它曾经相当可靠(旧版本的 Firefox)。我在 Firefox 29 或 38 上复制它没有遇到任何问题。Firefox 42 似乎降低了它的可能性,但它确实仍然发生。
我希望(尽管我可能是错的)Mozilla 会更改它以与其他浏览器保持一致,因为有人可能会争辩说它违反了 JavaScript 的 运行-to-completion任务的语义,这些语义刚刚被最新的规范加强和阐明。
我在 Firefox 和 Chrome 中都尝试过 this。在 Firefox 中,我得到了 10
的结果。在 Chrome 中,我得到了 0
的结果。可能 Firefox 和 Chrome 在涉及 confirm
函数时具有不同的并发模型。 Firefox 很可能 运行 在单独的线程中设置模态对话框,允许 setTimeout
在它自己的线程中继续 运行(并在 200 毫秒后增加 flag
的值). Chrome 很可能 运行 在与 setTimeout
相同的线程中连接模态对话框,因此阻塞了 setTimeout
的 运行 连接(并且不允许值flag
待递增)。
步骤:
- 运行 Firefox 中的代码
- 等待 5 秒(重要!)
- 按确定或取消
- 期望标志 == 0,但它是 10。
var flag;
function myFunction(){
flag = 0
console.info("initial", flag);
setTimeout(function(){
flag = 10;
}, 200);
confirm("conf");
alert("should be 0: "+flag);
}
document.getElementById('button').onclick=myFunction;
<button type="button" id="button">Click Me!</button>
什么?您 将 标志设置为 10。为什么您希望它为 0?
因为与许多浏览器不同,Firefox 可能 允许 JavaScript 线程 运行 其他代码,而 alert
、prompt
,并且显示 confirm
模态,暂停 current 代码。 (有关该句子中 "may" 的更多信息,请参阅答案结尾。)调用 alert
等的任务已暂停,因此该任务中的代码不会继续,但 其他 任务允许运行。
这意味着
计时器可以获得回调
Ajax 完成处理程序可以 运行
等
从来没有JavaScript运行宁并发在两个地方,但Firefox确实让线程运行其他任务,而一个任务是被那些模态暂停。
这是 Firefox 的一个怪癖。我首先是在 Stack Overflow 上了解到它的,thanks to bobince。
为什么我说 "may" 允许 JavaScript 线程 运行:它曾经相当可靠(旧版本的 Firefox)。我在 Firefox 29 或 38 上复制它没有遇到任何问题。Firefox 42 似乎降低了它的可能性,但它确实仍然发生。
我希望(尽管我可能是错的)Mozilla 会更改它以与其他浏览器保持一致,因为有人可能会争辩说它违反了 JavaScript 的 运行-to-completion任务的语义,这些语义刚刚被最新的规范加强和阐明。
我在 Firefox 和 Chrome 中都尝试过 this。在 Firefox 中,我得到了 10
的结果。在 Chrome 中,我得到了 0
的结果。可能 Firefox 和 Chrome 在涉及 confirm
函数时具有不同的并发模型。 Firefox 很可能 运行 在单独的线程中设置模态对话框,允许 setTimeout
在它自己的线程中继续 运行(并在 200 毫秒后增加 flag
的值). Chrome 很可能 运行 在与 setTimeout
相同的线程中连接模态对话框,因此阻塞了 setTimeout
的 运行 连接(并且不允许值flag
待递增)。