微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

JavaScript-setTimeout被连续的AJAX请求阻止了?

我正在解决使用setTimeout通知后端使会话保持活动状态的Web应用程序上的问题.除以下情况外,这在所有情况下均按预期工作:

发生背靠背同步AJAX帖子时,不会触发setTimeout.

我知道setTimeout触发可能会延迟为JavaScript is single-threaded,并且必须等待一项任务完成.

我的问题是:为什么setTimeout根本不触发?为什么在所有AJAX请求的末尾而不在两者之间触发?

这是我的keepAlive函数

function keepAlive() {
    var img = new Image(1, 1);
    img.src = "google.com" + '?' + new Date();

    timer = setTimeout(function () {
        keepAlive();
    }, 10000);
}

我在jsfiddle中创建了我的问题的快速脏目录demo.

提前致谢!

解决方法:

The setTimeout is not triggering while there are back to back sync AJAX posts happening.

My question is: Why is the setTimeout not firing at all? Why is it fired at the end of all the AJAX requests and not in between?

因为它们是同步请求.这是不使用同步请求的众多原因之一.改用异步请求.

当ajax请求是同步的时,它就像一个函数调用:它将主UI线程绑定在一起.所以:

doThisSyncRequest();
doThatSyncRequest();
doTheOtherSyncRequest();

在上述任何时候,线程都不会返回空闲状态并查看其排队的工作,因此排队的setTimeout回调无法运行.

UI主线程通过任务队列工作:

>任务队列为空时空闲
>当发生某种情况时(一般意义上的“事件”,包括计时器到期,正在添加代码等),浏览器会将带有关联JavaScript代码的任务排队,以供主UI线程拾取
>当主UI线程接收任务时,它将不间断地运行相关代码
>如果在代码运行时发生其他事情,浏览器会将这些事情的任务排队,并在队列中等待
>当主UI线程完成了一项任务的代码运行时,它将从队列中拾取下一个任务(如果有)或返回到空闲状态

由于同步请求占用了线程,因此它们在运行时始终停留在#3中,其他任何事物都排队等待.

当您使用异步请求时,启动它们的JavaScript代码在运行时不会被阻止;相反,代码流将继续并完成,并且主UI线程可以继续处理后续任务.最终,异步请求的状态更改(例如,它完成了),这使任务排队以调用就绪状态更改回调.

由于多种原因,我建议使用异步请求,包括由于UI在请求期间锁定而导致同步请求带来糟糕的用户体验.但是为了完整起见,您确实有另一种选择:您可以移动该后台ajax调用,以使会话保持活动到web worker线程中.然后,由于它在不同的线程上运行,因此主UI线程上的同步ajax调用不会阻止它运行.我不建议这样做(我建议改用异步请求),只是将其标记一个选项.在所有现代桌面浏览器(但不是IE9和更早版本)中的Web worker are supported上,移动支持正在改善,并且很容易进行功能检测以了解是否支持它们,如果不支持,则退回到使用主UI线程.但是实际上,异步请求是解决之道.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐