简体   繁体   中英

Synchronous AJAX call not truly synchronous

I'm having trouble with a synchronous AJAX request.

I am creating a web application where there are many AJAX requests called in sequence which should be returned in strict order. Rather than putting every succeeding request in the readystatechange event handler of the last request, I decided to simply call them synchronously.

However, in the following code, alert() is invoked before adding the response to the DOM.

window.addEventListener("load", main, false);

function main (e) {

    // Sending synchronous request
    var request = new XMLHttpRequest();
        request.open("GET", fileName, false);
        request.overrideMimeType("text/xml");
        request.send(null);

    // Receiving response
    var response = request.responseXML;

    // Changing XML Tree to corresponding XHTML Tree
    response = XMLtoXHTML(response);

    //Adding response to the body
    document.body.appendChild(response);

    // Calling alert
    alert("Hello World");

}

The response gets in fact successfully added to the DOM , but only after clicking OK on the alert message. When I do a walkthrough using Safari's Script Debugging features, the response does get added to the DOM before calling alert().

Any suggestions?

NB: I left out other requests.

I guess it actually does get added, you just don't see the changes before JS returns control back to the browser, ie until alert window is closed. If you cannot do an async request (which I would suggest first), you could at least make dom changes in a separate setTimeout ed "thread".

It has indeed been added to the DOM but the page hasn't parsed the new element into view yet. If I had to guess it would be that since alert blocks the current running JS thread webkit tries to perform reflows during this time for efficiency.

Test case:

function foo()
{
   var div = document.createElement("div");
   div.innerHTML = "hi friends";
   div.id = "bar";
   document.body.appendChild(div);
   alert(document.getElementById("bar").innerHTML);
}

Do you need the element to appear before the alert comes up? Use this in that case

setTimeout(function(){alert("Hello World");}, 1);

Or use a flow control library like Frame.js (or asnyc, flow.js, more):

Frame(function(next)){ 
    document.body.appendChild(response);
    next();
});
Frame(function(next)){ 
    alert("Hello World");
    next();
});
Frame.init();

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