views:

156

answers:

3

I'm looking to setup a web page that samples data via AJAX calls from an embedded web-server. How would I set up the code so that one request doesn't overlap another? I should mention I have very little JavaScript experience and also a compelling reason not to use external libraries of any size bigger than maybe 10 or so kilobytes.

+1  A: 

AJAX, despite the name, need not be asynchronous.

Here is the asynchronous method...

var req;

function ajax(method,url,payload,action)
    {
    if (window.XMLHttpRequest)
     {
     req = new XMLHttpRequest();
     req.onreadystatechange = action;
     req.open(method, url, true);
     req.send(payload);
     }
    else if (window.ActiveXObject)
     {
     req = new ActiveXObject("Microsoft.XMLHTTP");
     if (req)
      {
      req.onreadystatechange = action;
      req.open(method, url, true);
      req.send(payload);
      }
     else
      {
      alert("Could not create ActiveXObject(Microsoft.XMLHTTP)");
      }
     }
    }

...but here is a synchronous equivalent...

function sjax(method,url,payload,action)
    {
    if (window.XMLHttpRequest)
     {
     req = new XMLHttpRequest();
     req.open(method, url, false);
     req.send(payload);
     action();
     }
    else if (window.ActiveXObject)
     {
     req = new ActiveXObject("Microsoft.XMLHTTP");
     if (req)
      {
      req.onreadystatechange = action;
      req.open(method, url, false);
      req.send(payload);
      }
     else
      {
      alert("Could not create ActiveXObject(Microsoft.XMLHTTP)");
      }
     }
    }

... and here is a typical action ...

function insertHtml(target)
    {
    var pageTarget = arguments[0];
    if (req.readyState == 4) // 4 == "loaded"
     {
     if (req.status == 200) // 200 == "Ok"
      {
      if (req.responseText.indexOf("error") >= 0)
       {
       alert("Please report the following error...");
       pretty = req.responseText.substring(req.responseText.indexOf("error"),1200);
       pretty = pretty.substring(0,pretty.indexOf("\""));
       alert(pretty + "\n\n" + req.responseText.substring(0,1200));
       }
      else
       {
       div = document.getElementById(pageTarget);
       div.innerHTML = req.responseText;
       dimOff();
       }
      }
     else
      {
      alert("Could not retreive URL:\n" + req.statusText);
      }
     }
    }
dacracot
synchronous requests aren't really the best idea, in my opinion, they lock up the rest of the page as well.... but this depends on the user's requirements. also, from jQuery $.ajax docs: "It is better to block user interaction by other means when synchronization is necessary."
Dan Beam
A: 

I suggest you use a small toolkit like jx.js (source). You can find it here: http://www.openjs.com/scripts/jx/ (less than 1k minified)

To setup a request:

jx.load('somepage.php', function(data){
    alert(data); // Do what you want with the 'data' variable.
});

To set it up on an interval you can use setInterval and a variable to store whether or not a request is currently occuring - if it is, we simple do nothing:

var activeRequest = false;
setInterval(function(){

    if (!activeRequest) {
        // Only runs if no request is currently occuring:
        jx.load('somepage.php', function(data){
            activeRequest = false;
            alert(data); // Do what you want with the 'data' variable.
        });
    }
    activeRequest = true;

}, 5000); // Every five seconds
J-P
Same as the other answer... So why waste the interval, rather just make synchronous calls. You will on average waste 5000ms/2 by polling.
dacracot
+4  A: 

You may want to consider the option of relaunching your AJAX request ONLY after a successful response from the previous AJAX call.

function autoUpdate()
{
    var ajaxConnection = new Ext.data.Connection();

    ajaxConnection.request(
    {
        method:         'GET',
        url:            '/web-service/', 

        success: function(response) 
        {
            // Add your logic here for a successful AJAX response.
            // ...
            // ...

            // Relaunch the autoUpdate() function in 5 seconds.
            setTimeout(autoUpdate, 5000);
        }
    }
}

This example uses ExtJS, but you could very easily use just XMLHttpRequest.

NOTE: If you must have an exact interval of x seconds, you would have to keep track of the time passed from when the AJAX request was launched up to the setTimeout() call, and then subtract this timespan from the delay. Otherwise, the interval time in the above example will vary with the network latency and with the time to processes the web service logic.

Daniel Vassallo
not exactly what they were asking, but a very good solution (just to use callbacks)
Dan Beam