所以这真是烦我,我不知道它是否是一个浏览器相关的故障或javascript只是这样工作(我希望它)。我创造了一个小提琴。 https://jsbin.com/laluziqede/1/edit?html,js,output
打开控制台,然后单击按钮。当对话框出现时,该功能正常继续(第一个console.log没有暂停),但是setTimeout函数内的一个暂停,只有在你点击“停留在页面上”后才能显示。
但为什么,有人可以解释一下吗?我想在我的应用程序中使用此属性(在用户单击停留后立即执行操作),但我不确定这是否是一个好习惯,是否适用于所有浏览器和设备。
编辑:这是bin中的代码:
$(window).on('beforeunload', function() {
return 'Check your console please and then click stay';
});
$('#click-me').on('click', function() {
window.location.href='about:blank';
console.log ('dialog won\'t stop me from showing');
var timer=setTimeout(function() {
console.log('this was paused by the dialog');
},0);
});
答案 0 :(得分:2)
Javascript是单线程的(除非你开始使用像WebWorkers和其他新技术这样的东西)。因此,计时器功能会安排要完成的任务,但是当其他所有操作都控制了javascript线程时,它将仅完成。因此,定时器只是异步,因为你要求在一段时间后完成一些工作,但它并不是真正的异步,因为某些东西可以在其他东西也被完成时完成。
这也适用于XHR请求之类的事情,即使XHR请求确实是异步调度的,所有响应都是一次同步处理的。
您的具体示例有点奇怪,因为它不是另一个阻止的javascript函数,它是一个浏览器安全功能,确保您希望让以前的javascript操作将您带离当前页面。但这个概念是一样的。
答案 1 :(得分:2)
该行为取决于浏览器。我在Firefox,Chrome,IE和Edge中进行了测试,而且只有Chrome才有你描述的行为。
不同之处在于触发beforeunload
事件或处理事件时。大多数浏览器在您更改location属性时立即触发事件并立即处理它。当导航实际即将发生时,Chrome会触发并处理事件,或者将事件放在队列中并稍后像常规事件一样处理它。
在Chrome中,setTimeout
处理程序中的代码在处理beforeunload
事件之后才会发生,因为导航是在任何排队事件之前处理的,或者因为timout事件是在卸载之后队列中的事件。