简体   繁体   中英

Timer based Ajax call with 2 calls on one page

Is it possible to have multiple ajax calls on the same page, at the same time to different receiving div tags? I am struggling with finding answer to this.

I have 3 pages. A home page and 2 php pages: status and alert pages echoing the results.

Inside the home page I have 2 divs that get their data changed using ajax.

<div id="statusTable"> </div>

<div id="alertsTable"> </div>

Using setInterval I make 2 requests for new data for the divs at the same time. My problem is that both divs have the same data in them once the call is made - it's as if only one call was made for both.

setInterval
    (
        function()
        {
            getAlerts();
            getStatus();
        },
        1000 
    );

I get this eg.

alerts table // getStatus() call
2 2
2 2

status table // getStatus()
2 2
2 2

instead of

alerts table //getAlerts()
1 1
1 1

status table //getStatus()
2 2
2 2

This is the code:

function loadXMLDoc(url,cfunc)
    {
        if (window.XMLHttpRequest)
        {// code for IE7+, Firefox, Chrome, Opera, Safari
            xmlhttp=new XMLHttpRequest();
        }
        else
        {// code for IE6, IE5
            xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
         }
        xmlhttp.onreadystatechange=cfunc;
        xmlhttp.open("GET",url,true);
        xmlhttp.send();
    }

    function getAlerts()
    {
        loadXMLDoc("alerts.php?update=variable",function()
        {
            if (xmlhttp.readyState==4 && xmlhttp.status==200)
            {
            document.getElementById("alertsTable").innerHTML=xmlhttp.responseText;
            }
        });
    }

    function getStatus()
    {
        loadXMLDoc("status.php?update=variable",function()
        {
            if (xmlhttp.readyState==4 && xmlhttp.status==200)
            {
                document.getElementById("statusTable").innerHTML=xmlhttp.responseText;
            }
        });
    }

I changed the timer setIntervals so the calls don't overlap the data received in the divs like below

    setInterval
    (
        function()
        {
            getAlerts();
        },
        5000 
    );

    setInterval
    (
        function()
        {
            getStatus();
        },
        3000
    );

I am hoping there is a way to make a call at the same time and not have to worry about my divs having the same content.

First, AJAX uses HTTP protocol which is stateless. If you can't be sure which answer reached first unless you tag them yourself in the response body.

Maybe the 2 reaches first and set, as receiving only one packet results in readyState change and drops other.

Your xmlhttp variable is defined globally. So by that, the packet with 1 inside is overloaded by packet with 2 inside. Try using var xmlhttp while defining it in your getAlert and getStatus functions and provide it to your loadXMLDoc function as a parameter.

Second, make sure whether the results should be different or not. Maybe it is just a coincident that both values are the same.

You need to decalre the xmlhttp variable locally in loadXMLDoc()

function loadXMLDoc(url,cfunc)
{
    var xmlhttp;
    if (window.XMLHttpRequest)
    {// code for IE7+, Firefox, Chrome, Opera, Safari
        xmlhttp=new XMLHttpRequest();
    }
    else
    {// code for IE6, IE5
        xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
     }
    xmlhttp.onreadystatechange=cfunc;
    xmlhttp.open("GET",url,true);
    xmlhttp.send();
}

Without doing this, the xmlhttp value that is improperly declared in the function "leaks" into the global scope, meaning that you end up overwriting the values with whichever is called second (including the url value set on the object). You in essence introduce a race condition into your code due to asynchronous nature of the calls.

The race condition and the xmlhttp being global are the problems here. What ever came last is overwriting the data written in the divs. Solve it by making xmlhttp variable local as per suggestions and tagging the response body.

function loadXMLDoc(xmlhttp,url,cfunc)
{
    xmlhttp.onreadystatechange=cfunc;
    xmlhttp.open("GET",url,true);
    xmlhttp.send();
}

function getAlerts()
{
    var xmlhttp;
    if (window.XMLHttpRequest)
    {// code for IE7+, Firefox, Chrome, Opera, Safari
        xmlhttp=new XMLHttpRequest();
    }
    else
    {// code for IE6, IE5
        xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
    }
    loadXMLDoc(xmlhttp,"alerts.php?update=variable",function()
    {
       if (xmlhttp.readyState==4 && xmlhttp.status==200 && xmlhttp.responseText.indexOf("unique     key") != -1)
       {
          //change div which matches unique key
       }
    });
}

Credit: @Mike Brant and @Cunning

Before people like me want to continue and use more ajax calls check out how browsers handle and process multiple ajax calls:

How many concurrent AJAX (XmlHttpRequest) requests are allowed in popular browsers?

http://sgdev-blog.blogspot.com/2014/01/maximum-concurrent-connection-to-same.html

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM