为什么“留在页面上”对话框会暂停异步功能?

时间:2015-08-31 16:53:37

标签: javascript settimeout blocking onbeforeunload

所以这真是烦我,我不知道它是否是一个浏览器相关的故障或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);

});

2 个答案:

答案 0 :(得分:2)

Javascript是单线程的(除非你开始使用像WebWorkers和其他新技术这样的东西)。因此,计时器功能会安排要完成的任务,但是当其他所有操作都控制了javascript线程时,它将完成。因此,定时器只是异步,因为你要求在一段时间后完成一些工作,但它并不是真正的异步,因为某些东西可以在其他东西也被完成时完成。

这也适用于XHR请求之类的事情,即使XHR请求确实是异步调度的,所有响应都是一次同步处理的。

您的具体示例有点奇怪,因为它不是另一个阻止的javascript函数,它是一个浏览器安全功能,确保您希望让以前的javascript操作将您带离当前页面。但这个概念是一样的。

答案 1 :(得分:2)

该行为取决于浏览器。我在Firefox,Chrome,IE和Edge中进行了测试,而且只有Chrome才有你描述的行为。

不同之处在于触发beforeunload事件或处理事件时。大多数浏览器在您更改location属性时立即触发事件并立即处理它。当导航实际即将发生时,Chrome会触发并处理事件,或者将事件放在队列中并稍后像常规事件一样处理它。

在Chrome中,setTimeout处理程序中的代码在处理beforeunload事件之后才会发生,因为导航是在任何排队事件之前处理的,或者因为timout事件是在卸载之后队列中的事件。