CamelCamelCamel
CamelCamelCamel

Reputation: 5200

setTimeout for XHR requests

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?

Upvotes: 5

Views: 4457

Answers (2)

Frédéric Hamidi
Frédéric Hamidi

Reputation: 262929

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() (through loop()) from the delayed function itself only reimplements a poorer setInterval(). You indeed have to call loop() from the AJAX callback to obtain the expected behavior.

Upvotes: 4

Shadow Wizard
Shadow Wizard

Reputation: 66389

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 the setTimeout() as well to ensure it will "wait" the proper amount of time before polling again.

Upvotes: 2

Related Questions