Ajax Long Polling to your RESTful API

Hello!

Whether your developing a mobile or web based application, keeping on top of constantly changing data is a challenge on its own. Sometimes its necessary to make repeated calls to your API to pull updates at regular intervals.

We wrote a previous blog post describing how to use Ajax to pull JSON data via a RESTful web API (click here to read it).

Somewhat extending that sentiment a bit, we would like to walk through the process of creating an Ajax “polling” process that repeatedly polls the API to pull data over and over again. This will allow you to receive, process and manipulate or display the data as it changes.

The context through which we are using this process is to display changes made to a google map via geo-location updates to a centralized API server that processes updates and returns them to the end users. This particular context is within an Angular Javascript based framework, but it really can be used anywhere that supports Ajax + Javascript.

Here’s the first part of the polling process :

               (function poll() {
                setTimeout(function() {
                           $.ajax({
                                  url: "https://yoursite.com/request",
                                  headers: {
                                  'Content-Type': 'application/x-www-form-urlencoded'
                                  },
                                  type: "GET",
                                  success: function(data) {

What we’re doing above is defining a “poll” function that will essentially be calling itself at set intervals. Within the function there will be a “success” and “error” function nested within. Those functions can be utilized to execute additional checks and balances in order to ensure the data is sanitized and to catch any subsequent errors at every step of the way.

For example, in the “success” function, you could do something like this :

       success: function(data) {
           // check if null return (no results from API)
           if (data == null) {
               // do something if no data is returned, perhaps display static info, reset some arrays or display an error message
          } else { 
               $.each(data, function(index, element) {
                   arrayName.push(element.whatever);
          }
       }

What were doing is checking if the data pulled from the Ajax request is null. If its null, we can do various things such as clear variables or display an error message perhaps. If its not empty, then we will iterate what we will be expecting to be an array of data. We then “push” each iteration into our own array apty named arrayName.

The next step is key. Because we are pulling data at polling intervals, its possible that we will see data that already exists in our array (or ultimately wherever we would be internally storing the data). What we want to do is implement a check within the poll to see if the data returned actually matches what we might already have. If a match happens, then we probably want to ignore it. This is more of a requirement specific to our needs in the context of our project, but I thought to include it here because its interesting and hopefully useful to others.

for (var i = 0; i < arrayName.length; i++) {
    // check if new data received matches what is in internal array
    if (arrayName[i][0] === element.whatever1 && arrayName[i][1] === element.whatever2) {
        console.log('data received is already in array .. skipping');
    } else {
        console.log('new data received! processing ...');
    }

What I'm doing above (in the context of google maps) is checking the latitude and longitude of our internal array against the iterated data. As such, we need to check both the latitude and longitude at the same time (you need both to plot a point on a map, obviously).

You could easily rewrite the above code to only check one element instead of two.

The last part of the code snippet simply defines the polling interval variables such as "timeout" and the actual polling interval (all in milliseconds) :

       }
    })
  }

 },
     dataType: "json",
     complete: poll,
     timeout: 2000
 })
}, 3000);
})();

Pretty straightforward! Find the entire code snippet below , for your reference :

              (function poll() {
                setTimeout(function() {
                           $.ajax({
                                  url: "https://yoursite.com/request",
                                  headers: {
                                  'Content-Type': 'application/x-www-form-urlencoded'
                                  },
                                  type: "GET",
                                  success: function(data) {

                                  // check if null return (no results from API)
                                  if (data == null) {
                                        console.log('no data!');
                                  } else {
                                        $.each(data, function(index, element) {
                                               arrayName.push([element.whatever1, element.whatever2]);
                                               // cycle through internal array to see if match, or existing coordinates
                                               for (var i = 0; i < arrayName.length; i++) {
                                                    // check if new data received matches what is in internal array
                                                    if (arrayName[i][0] === element.whatever1 && arrayName[i][1] === element.whatever2) {
                                                        console.log('data received is already in array .. skipping');
                                                    } else {
                                                        console.log('new data!');
                                                    }
                                               }
                                         })
                                  }

                                  },
                                  dataType: "json",
                                  complete: poll,
                                  timeout: 2000
                                  })
                           }, 3000);
                })();