Reputation: 332
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?
Upvotes: 3
Views: 328
Reputation: 32063
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.
Upvotes: 1