Let's say I have a function that does a standard AJAX request:
function doXHR() {
var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://jsonplaceholder.typicode.com/posts');
xhr.send();
xhr.onreadystatechange = () => {
console.log('ready state change');
};
}
doXHR();
console.log('done');
This code will cause the browser to start an AJAX request, but at what point in the function does the request actually start? According to this post: https://blog.raananweber.com/2015/06/17/no-there-are-no-race-conditions-in-javascript/
[Calling
xhr.onreadystate()
aftersend()
] is possible, because the HTTP request is only executed after the current scope has ended its tasks. This enables the programmer to set the callbacks at any position he wishes. As JavaScript is single-threaded, the request can only be sent when this one single thread is free to run new tasks. The HTTP request is added to the list of tasks to be executed, that is managed by the engine.
But when I add a breakpoint in devtools right after the send call:
I do get a network request, albeit in a pending state:
At the breakpoint, the XHR's readystate
is 1, which is XMLHttpRequest.OPENED
. According to MDN's documentation, XMLHttpRequest.OPENED
means that xhr.open()
has been called: https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/readyState
But if I comment out xhr.send()
so that only .open()
is called:
Then I get no pending network request:
Thinking that perhaps I need the function scope to end in order for the request to actually be sent out, I moved the breakpoint to after the function call (and modified the code a bit to see the XHR readyState):
But I still get the pending network request:
It seems like the debugger not only freezes code execution, but also any network requests. This makes sense, as you don't want network requests to complete while you're on a breakpoint, but this also makes it impossible to tell when the network request is actually initiated.
My question is, at what point does the request actually get sent out? Does calling xhr.send()
merely set up the request, but requires that the function scope end before the request is initiated? Does xhr.send()
immediately initiate the request before the function scope ends? Or is there something else going on here?
When you make an AJAX request, your browser sends an HTTP request to a given address. The server on the other end of the request responds, and returns the data to your browser. This is the same thing that happens when you navigate to a new web page.
How AJAX Calls Work. AJAX uses both a browser built-in XMLHttpRequest object to get data from the web server and JavaScript and HTML DOM to display that content to the user. Despite the name “AJAX” these calls can also transport data as plain text or JSON instead of XML.
In Laravel, we can use $request->ajax() method to check request is ajax or not.
By default, Ajax requests are sent using the GET HTTP method. If the POST method is required, the method can be specified by setting a value for the type option. This option affects how the contents of the data option are sent to the server.
send
immediately initiates the request. This is at least hinted at by MDN's documentation for send
.
The author of the blog you link to is correct that there are no race conditions per-se, but that does not keep you from having things happen out-of-order. An example of this would be if you load multiple <script>
tags in with the async=true
set on them. In this case, if one script depends on the other, you could end up in a situation where you have an unpredictable sequence of events (which is very similar to a race condition) because two asynchronous events finish at different times.
It is true that you can set onreadystatechange
after calling send
because even if the request request failed immediately, the event won't get dispatched until the function scope completes. The delay here is not in the dispatching of the network request, but in the dispatching of the event to say that the network request completed.
It is important to note, that networking itself is not handled in JavaScript, but rather by the browser implementation, which is native code, and could be multi-threaded (although I do not know if it is). This means that the browser is perfectly capable of handling network tasks while your javascript is running.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With