引用MDC:
如果您的逻辑可能需要比间隔时间更长的时间来执行,建议您使用window.setTimeout递归调用命名函数。例如,如果使用setInterval每5秒轮询一次远程服务器,网络延迟,无响应的服务器以及许多其他问题可能会阻止请求在其分配的时间内完成。因此,您可能会发现自己排队的XHR请求不一定按顺序返回。
对于这种情况,首选递归setTimeout模式:
(function loop(){
setTimeout(function(){
// logic here
// recurse
loop();
}, 1000);
})();
在上面的代码片段中,声明了一个命名的函数循环并立即执行。在逻辑完成执行后,在setTimeout内递归调用循环。虽然这种模式不能保证在固定的时间间隔内执行,但它确保在递归之前完成了前一个时间间隔。
我不明白这是如何解决这个问题的。我不应该从XHR回调中调用loop()而不是从setTimeout调用吗?
答案 0 :(得分:5)
原始问题与setInterval()
有关:在收到对第一个的回复之前,可能会发送两个或更多个AJAX请求(取决于网络延迟和计时器延迟)。如果发生这种情况,则无法保证按顺序调用它们各自的回调。
解决方案是使用setTimeout()
独立延迟每个请求,并仅在当前请求返回后(即在该请求的回调中)安排下一个请求。
所以,你是绝对正确的:从延迟函数本身调用setTimeout()
(通过loop()
)只会重新实现更穷的setInterval()
。您确实必须从AJAX回调中调用loop()
以获得预期的行为。
答案 1 :(得分:2)
目前的问题不是执行单个XHR请求,而是定期向服务器重复发送请求。
假设您希望每五秒轮询一次服务器并解析响应。您只需使用setInterval()
即可创建XHR请求并每五秒发送一次。
现在,如果流量中存在一些阻塞或服务器缓慢/过载,则有可能发送请求A并且当您发送请求B时服务器没有完成处理它 - 这就是“排队的XHR请求”的含义“据我了解。
我认为解决方案根本不是使用setInterval()
,而是仅在前一个请求的回调中调用“下一个”XHR请求,可能也使用setTimeout()
确保它会在再次轮询之前“等待”适当的时间。