setTimeout 被连续 AJAX 个请求阻塞?
setTimeout blocked by continuous AJAX requests?
我修复了一个 Web 应用程序的问题,该应用程序使用 setTimeout 通知后端保持会话活动。除以下情况外,这在所有情况下都按预期工作:
当发生背对背同步 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线程接任务时,运行执行相关代码不间断
如果在该代码 运行ning 期间发生其他事情,浏览器会为这些事情排队任务,它们会在队列中等待
当主 UI 线程完成 运行 一个任务的代码时,它从队列中获取下一个任务(如果有的话)或返回空闲状态
由于同步请求占用了线程,它在 运行ning 时停留在 #3,其他任何东西都在排队。
当您使用 异步 请求时,启动它们的 JavaScript 代码在 运行ning 时不会被阻止;相反,代码流继续并完成,主 UI 线程可以继续处理后续任务。最终异步请求的状态发生变化(例如,它完成),这会将任务排队以调用就绪状态更改回调。
出于多种原因,我建议使用异步请求,包括同步请求会导致糟糕的用户体验,因为 UI 在请求期间锁定。但为了完整起见,您确实有一个替代方案:您可以将后台 ajax 调用移动到所有现代桌面浏览器(但不是 IE9 和更早版本)中的 web worker thread instead. Then, since it's running on a different thread, synchronous ajax calls on the main UI thread don't prevent it from running. I'm not recommending this (I recommend using async requests instead), just flagging it up as an option. Web workers are supported 中,移动支持是改进,并且很容易检测是否支持它们,如果不支持则回退到使用主 UI 线程。但实际上,异步请求才是正确的选择。
正如您提到的 Ajax 调用是同步的,这可能会阻止您的 setTimeout 触发。您可以通过让 Ajax 异步调用来尝试此操作。
谢谢
我修复了一个 Web 应用程序的问题,该应用程序使用 setTimeout 通知后端保持会话活动。除以下情况外,这在所有情况下都按预期工作:
当发生背对背同步 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线程接任务时,运行执行相关代码不间断
如果在该代码 运行ning 期间发生其他事情,浏览器会为这些事情排队任务,它们会在队列中等待
当主 UI 线程完成 运行 一个任务的代码时,它从队列中获取下一个任务(如果有的话)或返回空闲状态
由于同步请求占用了线程,它在 运行ning 时停留在 #3,其他任何东西都在排队。
当您使用 异步 请求时,启动它们的 JavaScript 代码在 运行ning 时不会被阻止;相反,代码流继续并完成,主 UI 线程可以继续处理后续任务。最终异步请求的状态发生变化(例如,它完成),这会将任务排队以调用就绪状态更改回调。
出于多种原因,我建议使用异步请求,包括同步请求会导致糟糕的用户体验,因为 UI 在请求期间锁定。但为了完整起见,您确实有一个替代方案:您可以将后台 ajax 调用移动到所有现代桌面浏览器(但不是 IE9 和更早版本)中的 web worker thread instead. Then, since it's running on a different thread, synchronous ajax calls on the main UI thread don't prevent it from running. I'm not recommending this (I recommend using async requests instead), just flagging it up as an option. Web workers are supported 中,移动支持是改进,并且很容易检测是否支持它们,如果不支持则回退到使用主 UI 线程。但实际上,异步请求才是正确的选择。
正如您提到的 Ajax 调用是同步的,这可能会阻止您的 setTimeout 触发。您可以通过让 Ajax 异步调用来尝试此操作。
谢谢