XHR 请求的 setTimeout
引用 MDC:
如果您的逻辑执行时间可能比间隔时间长,建议您使用 window.setTimeout 递归调用命名函数。例如,如果使用 setInterval 每 5 秒轮询一次远程服务器,网络延迟、服务器无响应以及许多其他问题可能会阻止请求在分配的时间内完成。因此,您可能会发现排队的 XHR 请求不一定按顺序返回。
对于这种情况,首选递归 setTimeout 模式:
(function loop(){
setTimeout(function(){
// logic here
// recurse
loop();
}, 1000);
})();
在上面的代码片段中,声明了一个命名函数循环并立即执行。逻辑执行完毕后,在setTimeout内部递归调用loop。虽然此模式不保证按固定间隔执行,但它确实保证前一个间隔在递归之前已完成。
我不明白这如何解决这个问题。我不应该从 XHR 回调内部而不是从 setTimeout 调用 Loop() 吗?
quoting MDC:
If there is a possibility that your logic could take longer to execute than the interval time, it is recommended that you recursively call a named function using window.setTimeout. For example, if using setInterval to poll a remote server every 5 seconds, network latency, an unresponsive server, and a host of other issues could prevent the request from completing in its alloted time. As such, you may find yourself with queued up XHR requests that won't necessarily return in order.
For such cases, a recursive setTimeout pattern is preferred:
(function loop(){
setTimeout(function(){
// logic here
// recurse
loop();
}, 1000);
})();
In the above snippet, a named function loop is declared and is immediately executed. loop is recursively called inside setTimeout after the logic has completed executing. While this pattern does not guarantee execution on a fixed interval, it does guarantee that the previous interval has completed before recursing.
I don't understand how this fixes the problem. Shouldn't I call loop() from inside the XHR callback and not from setTimeout?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
最初的问题与 setInterval() 相关:在收到第一个请求的回复之前,可能会发送两个或多个 AJAX 请求(取决于网络延迟和计时器延迟)。如果发生这种情况,则不能保证按顺序调用它们各自的回调。
解决方案是使用
setTimeout()
独立延迟每个请求,并且仅在当前请求返回后(即在该请求的回调中)安排下一个请求。所以,你是绝对正确的:从延迟函数本身调用
setTimeout()
(通过loop()
)只会重新实现较差的setInterval()
>。您确实必须从 AJAX 回调中调用loop()
才能获得预期的行为。The original problem is related to
setInterval()
: it's possible for two or more AJAX requests to be sent before the reply to the first one is received (depending on the network latency and the timer delay). If that happens, their respective callbacks are not guaranteed to be called in order.The solution is to delay each request independently with
setTimeout()
and only schedule the next request after the current request has returned (i.e. in that request's callback).So, you're absolutely right: calling
setTimeout()
(throughloop()
) from the delayed function itself only reimplements a poorersetInterval()
. You indeed have to callloop()
from the AJAX callback to obtain the expected behavior.当前的问题不是执行单个 XHR 请求,而是定期向服务器重复发送请求。
假设您想每五秒轮询一次服务器并解析响应。为此,您只需使用
setInterval()
即可,导致每五秒创建并发送一次 XHR 请求。现在,如果流量出现阻塞或服务器缓慢/过载,则有可能发送请求 A,但当您发送请求 B 时服务器尚未完成处理它 - 这就是他们所说的“排队 XHR 请求”的含义据我了解。
我认为解决方案根本不使用 setInterval() ,而是仅从上一个请求的回调中调用“下一个”XHR 请求,可能通过使用 setTimeout() 以及确保它在再次轮询之前“等待”适当的时间。
The issue at hand is not executing single XHR request but rather repeatedly sending requests to the server at regular intervals.
Suppose you want to poll the server every five seconds and parse the response. You will just use
setInterval()
for this, causing XHR request to be created and sent every five seconds.Now if there is some block in traffic or server is slow/overloaded there is chance that request A is sent and the server did not finish to process it when you send request B - that's what they mean by "queued up XHR requests" as far as I understand.
The solution in my opinion is not using
setInterval()
at all, but rather call the "next" XHR request only from within the callback of the previous request, possibly by using thesetTimeout()
as well to ensure it will "wait" the proper amount of time before polling again.