user1853871
user1853871

Reputation: 249

Javascript webservice polling

I have the following code which does a call to a webservice every 5 seconds. This websservice checks if there is anything in a list.

setTimeout(function () {
  _getListItems();
}, 5000);

However, instead of checking this every 5 seconds, I want to check it on the page load and every minute thereafter. If there is something found in the list, start calling it every 5 seconds. Can anyone help me with this?

Upvotes: 2

Views: 1591

Answers (2)

Greg Burghardt
Greg Burghardt

Reputation: 18783

Even though an answer has already been accepted, I'll post this since the combination of AJAX and setInterval allowed an application I was working on to take down a load balancer and knock all of the companies websites offline.

First, let's let's discuss the differences between setInterval and setTimeout with regard to AJAX polling.

Advantages of Using setInterval

  • Easy way to execute a function and fire off an AJAX request on a heartbeat
  • The code is easy to understand
  • AJAX requests are sent every X milliseconds without having to account for the time the request takes to come back

Disadvantages of Using setInterval

  • (and this is the big one) The next request doesn't wait for the current request to complete before it is sent. When systems start to run slow server side, these AJAX requests can pile up. For example, you send a request every 5 seconds, but it takes 10 seconds for the server to respond. In one minute, a single user can queue up 12 requests to the server that have yet to be returned to the client. Now multiply that by the number of concurrent users you have, and this number adds up quickly. Ten users means 120 requests are queued up. One hundred users = 1,200 requests queued up in a single minute. I worked at a place where we took down a load balancer doing this. They had to literally pull the plug on it because the power button didn't even work. Dead. In. The. Water... Down.
  • Authentication errors are more difficult to handle if the user's session times out, since you have to remember to clear the interval if the server returns a 401 Unauthorized response

Advantages of Using setTimeout

  • (and this is the big one) New requests are not sent before the current request is done being processed. This mitigates the disaster I explained above.
  • Authentication errors are easier to handle because new requests are not issued when a non 200 OK response is received from the server

Disadvantages of Using setTimeout

  • Your code is a little more complex as you need to restart the timeout after a successful AJAX call
  • The period between requests varies because the interval is actually: timeout + AJAX request time + response processing time, so a timeout of 5,000 milliseconds can give you an interval of roughly 5,500 milliseconds once you account for the time it takes the AJAX request to come back to the browser, and for the browser to process the response. You can account for this by keeping track of the AJAX request and processing time and subtracting that from your standard timeout period.

Basically, the consequence of using setTimeout is increased code complexity, but reduced risk of DDOS-ing your own system when things on the server side run slow.

Example of Using setTimeout

function poll(url, method, period, beforeRequest, onSuccess, onError) {
    var xhr = new XMLHttpRequest(),
        onReadyStateChange= function() {
            if (this.readyState === 4) {
                if (this.status === 200 || this.status === 201) {
                    onSuccess(xhr);
                    setTimeout(sendRequest, period);
                }
                else if (this.status > 399) {
                    // Allow error handling code to retry the operation
                    onError(xhr, sendRequest, period);
                }
            }
        },
        sendRequest = function() {
            var data = beforeRequest(xhr) || null;
            xhr.open(method, url, true);
            xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
            xhr.send(data);
        };

    xhr.onreadystatechange = onReadyStateChange;

    setTimeout(sendRequest, period);
}

And to use the function:

poll("/messages", "POST", 10000,
    function beforeRequest(xhr) {
        return "?user_id=123";
    },
    function onSuccess(xhr) {
        var data = JSON.parse(xhr.responseText);
        // show messages...
    },
    function onError(xhr, sendRequest, period) {
        if (xhr.status === 401) {
            // show dialog to log in user
        }
        else {
            // retry the operation
            setTimeout(sendRequest, period + 10000);
        }
    }
);

Upvotes: 5

Daniel W.
Daniel W.

Reputation: 32310

setTimeout only executes once after the given interval, what you have / mean is setInterval.

The return value of those methods is an identifier. Using this ID you can delete an interval.

How you can do this:

  1. initial check on document ready + apply setInterval with 1 minute (save the return value in a variable)

  2. if the function called every minute has items in the list, remove the 1-minute-interval, setup a new one that checks every 5 seconds

.

var intervalCall = window.setInterval(function() { }, 60000);

window.clearTimeout(intervalCall);

This is your reference: https://developer.mozilla.org/en-US/docs/Web/API/Window.setInterval

Upvotes: 2

Related Questions