1

In the following code, is doThisFirst() guaranteed to execute before doThisSecond()?

var xmlhttp = window.XMLHttpRequest ? new XMLHttpRequest() : 
    new ActiveXObject("Microsoft.XMLHTTP");
xmlhttp.onreadystatechange = function() {
    if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
        doThisSecond(xmlhttp.responseText);
    }
};
xmlhttp.open("GET", "/myscript.php?", true);
xmlhttp.send();
doThisFirst();

If not, how can I guarantee this execution order (aside from the naive solution of setting a flag at the end of doThisFirst() and then polling while(!flag); before executing doThisSecond())?. I'm looking for a pure-Javascript solution (no jquery).

Important note: I do not want to execute the AJAX request synchronously, which would execute doThisSecond() before doThisFirst().

1''
  • 26,823
  • 32
  • 143
  • 200

1 Answers1

3

doThisFirst() will execute synchronously after xmlhttp.send, and xmlhttp.onreadystatechange cannot be executed until the control flow has released back to the "Event Loop".


There is one catch. It may be possible* that the callback is executed as part of .send(), in which case doThisSecond would be executed first because the code never needed to release to the event loop. If you need to enforce an asynchronous behavior, simply wrapping doThisSecond as setTimeout(function () { doThisSecond(xmlhttp.response.Text) }, 1) will enforce that the function can not be called until the flow control is released to the event loop.

In your example it shouldn't make a difference, as I'm fairly certain that onreadystatechange is always called after the release to the event loop (synchronous XHR notwithstanding).

* whether by set to execute the AJAX call in a synchronous blocking manner, or due to caching, I honestly don't know enough of the XHR nuances cross-browser

Community
  • 1
  • 1
zzzzBov
  • 174,988
  • 54
  • 320
  • 367
  • Thanks for your answer. Does the number of messages sent to the event loop depend on the number of function calls or statements? For instance, if I put 10 statements after `doThisFirst()`, will they all execute before `xmlhttp.onreadystatechange`? – 1'' Sep 04 '13 at 00:24
  • @1'', the messages in the event loop are determined by the type of message, not the quantity. Event listeners and callbacks using `setTimeout` are the most common ways of queueing more calls in the event loop. In this case `onreadystatechange` is an event listener. – zzzzBov Sep 04 '13 at 00:30
  • This is my intuition as well, but I am trying to find documentation to support this. I've always wondered what happens when the content is cached. It is possible, I suppose, that `send()` could fire the `onreadystatechange` event. Do you know of documentation that requires that browsers respect the async nature of the `send()`? Or are you relying on existing implementation of the browsers? – Brian Genisio Sep 04 '13 at 00:30
  • @BrianGenisio, I don't know if [the documentation](http://www.w3.org/TR/XMLHttpRequest/) enforces the asynchronous nature of those event callbacks. More importantly, I don't know enough about the existing implementation to warn in the case of possible cross-browser inconsistencies. It's why I added the second bit about using `setTimeout` to enforce that the callback code enters the event loop. – zzzzBov Sep 04 '13 at 00:35
  • @zzzzBov I see your update. I think that clarifies your response a bit. The OP is asking if it is guaranteed. I can't find any spec that defines the behavior, so I think the answer is "Not guaranteed, but practical." I like your idea of enforcing the behavior, though there could still be subtile differences (I can't come up with any offhand). – Brian Genisio Sep 04 '13 at 01:09