jQuery AJAX polling for JSON response, handling based on AJAX result or JSON content
Asked Answered
C

4

46

I'm a novice-to-intermediate JavaScript/jQuery programmer, so concrete/executable examples would be very much appreciated.

My project requires using AJAX to poll a URL that returns JSON containing either content to be added to the DOM, or a message { "status" : "pending" } that indicates that the backend is still working on generating a JSON response with the content. The idea is that the first request to the URL triggers the backend to start building a JSON response (which is then cached), and subsequent calls check to see if this JSON is ready (in which case it's provided).

In my script, I need to poll this URL at 15-second intervals up to 1:30 mins., and do the following:

  • If the AJAX request results in an error, terminate the script.
  • If the AJAX request results in success, and the JSON content contains { "status" : "pending" }, continue polling.
  • If the AJAX request results in success, and the JSON content contains usable content (i.e. any valid response other than { "status" : "pending" }), then display that content, stop polling and terminate the script.

I've tried a few approaches with limited success, but I get the sense that they're all messier than they need to be. Here's a skeletal function I've used with success to make a single AJAX request at a time, which does its job if I get usable content from the JSON response:

// make the AJAX request
function ajax_request() {
  $.ajax({
    url: JSON_URL, // JSON_URL is a global variable
    dataType: 'json',
    error: function(xhr_data) {
      // terminate the script
    },
    success: function(xhr_data) {
      if (xhr_data.status == 'pending') {
        // continue polling
      } else {
        success(xhr_data);
      }
    },
    contentType: 'application/json'
  });
}

However, this function currently does nothing unless it receives a valid JSON response containing usable content.

I'm not sure what to do on the lines that are just comments. I suspect that another function should handle the polling, and call ajax_request() as needed, but I don't know the most elegant way for ajax_request() to communicate its results back to the polling function so that it can respond appropriately.

Any help is very much appreciated! Please let me know if I can provide any more information. Thanks!

Concupiscence answered 10/9, 2009 at 17:18 Comment(0)
S
47

You could use a simple timeout to recursively call ajax_request.

success: function(xhr_data) {
  console.log(xhr_data);
  if (xhr_data.status == 'pending') {
    setTimeout(function() { ajax_request(); }, 15000); // wait 15 seconds than call ajax request again
  } else {
    success(xhr_data);
  }
}

Stick a counter check around that line and you've got a max number of polls.

if (xhr_data.status == 'pending') {
  if (cnt < 6) {
    cnt++;
    setTimeout(function() { ajax_request(); }, 15000); // wait 15 seconds than call ajax request again
  }
}

You don't need to do anything in your error function unless you want to put an alert up or something. the simple fact that it error will prevent the success function from being called and possibly triggering another poll.

Semipermeable answered 10/9, 2009 at 17:25 Comment(3)
Does setTimeout() block the execution of the rest of the script during the delay periods?Reahard
No. setTimeout() specifies some time interval in the future for a block of code to be executed. The rest of the script will only be blocked when the timeout expires and the code is run.Semipermeable
“In short loops, it's better to just do setTimeout to give it some breathing room. At some point, you might use setInterval() to poll a function every 50ms, or something. It's possible in that case that there's not enough time to complete what you're trying to do before the time is up to do it again.” --sourceReduplicative
D
4

thank you very much for the function. It is a little bit buggy, but here is the fix. roosteronacid's answer doesn't stop after reaching the 100%, because there is wrong usage of the clearInterval function.

Here is a working function:

$(function ()
{
    var statusElement = $("#status");

    // this function will run each 1000 ms until stopped with clearInterval()
    var i = setInterval(function ()
    {
        $.ajax(
        {
            success: function (json)
            {
                // progress from 1-100
                statusElement.text(json.progress + "%");

                // when the worker process is done (reached 100%), stop execution
                if (json.progress == 100) clearInterval(i);
            },

            error: function ()
            {
                // on error, stop execution
                clearInterval(i);
            }
        });
    }, 1000);
});

The clearInterval() function is becomming the interval id as parameter and then everything is fine ;-)

Cheers Nik

Dupuy answered 18/8, 2010 at 9:11 Comment(0)
R
3

Off the top of my head:

$(function ()
{
    // reference cache to speed up the process of querying for the status element
    var statusElement = $("#status");

    // this function will run each 1000 ms until stopped with clearInterval()
    var i = setInterval(function ()
    {
        $.ajax(
        {
            success: function (json)
            {
                // progress from 1-100
                statusElement.text(json.progress + "%");

                // when the worker process is done (reached 100%), stop execution
                if (json.progress == 100) i.clearInterval();
            },

            error: function ()
            {
                // on error, stop execution
                i.clearInterval();
            }
        });
    }, 1000);
});
Randee answered 10/9, 2009 at 17:25 Comment(1)
Thanks for the reply! I found that Joel Potter's solution worked better in my situation - this is useful, though.Concupiscence
C
0

You can use javascript setInterval function to load the contents each and every 5 sec.

var auto= $('#content'), refreshed_content; 
    refreshed_content = setInterval(function(){
    auto.fadeOut('slow').load("result.php).fadeIn("slow");}, 
    3000);

For your reference-

Auto refresh div content every 3 sec

Conradconrade answered 30/8, 2014 at 22:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.