Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why Firefox executes XMLHttpRequest differently compared to Chrome/IE?

I'm sending two requests with XMLHttpRequest in a function. First one is asynchronous, second is synchronous. As in the example below:

onload = function () {
    this.console.log('*** start onload');
    sendRequest('async - 1', true);
    sendRequest('NOT async - 2', false);
    console.log('*** end of onload');
} 

function sendRequest(id, isAsync) {
var req = new XMLHttpRequest();
    req.id = id;
    req.onreadystatechange = function () {
        console.log(req.id, " => " ,'readyState: ', req.readyState, ' <= onreadystatechange');
    }

    req.open("POST", 'http://localhost:3009/, isAsync);

    req.setRequestHeader("Content-Type", "text/plain");
    console.log('-> before send() ', id);
    req.send("MyText");
    console.log('-> after send() ', id);
}

In Chrome/IE I get logs like:

*** start onload
async - 1  =>  readyState:  1  <= onreadystatechange
-> before send()  async - 1
after send()  async - 1
NOT async - 2  =>  readyState:  1  <= onreadystatechange
-> before send()  NOT async - 2
NOT async - 2  =>  readyState:  4  <= onreadystatechange
-> after send()  NOT async - 2
*** end of onload
async - 1  =>  readyState:  2  <= onreadystatechange
async - 1  =>  readyState:  3  <= onreadystatechange
async - 1  =>  readyState:  4  <= onreadystatechange

In Firefox :

*** start onload
async - 1  =>  readyState:  1  <= onreadystatechange
-> before send()  async - 1
-> after send()  async - 1
NOT async - 2  =>  readyState:  1  <= onreadystatechange
-> before send()  NOT async - 2
async - 1  =>  readyState:  2  <= onreadystatechange
async - 1  =>  readyState:  3  <= onreadystatechange
async - 1  =>  readyState:  4  <= onreadystatechange
NOT async - 2  =>  readyState:  4  <= onreadystatechange
-> after send()  NOT async - 2 
*** end of onload

I expect the callbacks for async requests to be called when javascript "is not doing anything" in my case after onload function as is happens in chrome/IE.

As i can see the req.send(txt) triggers onreadystatechange in Firefox.

Does Firefox execute these kind of requests differently?

like image 840
UnnamedXAer Avatar asked Feb 05 '26 10:02

UnnamedXAer


1 Answers

This is a known bug #697151 in Firefox: "Synchronous XMLHttpRequest (XHR) does not block readyState events for async XHR."

Because JS has so-called "Run-to-completion" semantics, synchronous APIs must freeze the page while they wait for something synchronously. For this reason using synchronous XMLHttpRequest is not recommended.

But actually freezing the page (or - in non-multiprocess browsers - even the whole browser) is deemed unfriendly to the user, so the browsers may cheat by spinning an "inner" event loop while waiting during the synchronous API call (xhr.send() in your case). The browser has to decide which events are eligible to be processed in such nested event loop: for example processing page scrolling is probably good to run in the inner event loop, while running JS listeners from this loop ought to be avoided.

Firefox has this inner loop, but unlike other browsers doesn't postpone the events from the async XHR until the outer (main) loop is ready.

like image 140
Nickolay Avatar answered Feb 07 '26 22:02

Nickolay



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!