How does JavaScript handle AJAX responses in the background?
Asked Answered
B

3

147

Since JavaScript runs in a single thread, after an AJAX request is made, what actually happens in the background? I would like to get a deeper insight into this, can anyone shed some light?

Booboo answered 27/9, 2011 at 20:58 Comment(4)
A pretty good description is here: https://mcmap.net/q/36614/-ajax-multi-threadedDesmid
JavaScript code is single threaded (except for web workers), but not the browser that is running the JavaScript engine...Reporter
@JuanMendes Does the JavaScript run in one thread while the Event Queue runs in another thread?Devoid
@ShaunLuttin No, the event queue is what kicks off JavaScriptReporter
V
233

Below the covers, javascript has an event queue. Each time a javascript thread of execution finishes, it checks to see if there is another event in the queue to process. If there is, it pulls it off the queue and triggers that event (like a mouse click, for example).

The native code networking that lies under the ajax call will know when the ajax response is done and an event will get added to the javascript event queue. How the native code knows when the ajax call is done depends upon the implementation. It may be implemented with threads or it may also be event driven itself (it doesn't really matter). The point of the implementation is that when the ajax response is done, some native code will know it's done and put an event into the JS queue.

If no Javascript is running at the time, the event will be immediately triggered which will run the ajax response handler. If something is running at the time, then the event will get processed when the current javascript thread of execution finishes. There doesn't need to be any polling by the javascript engine. When a piece of Javascript finishes executing, the JS engine just checks the event queue to see if there is anything else that needs to run. If so, it pops the next event off the queue and executes it (calling one or more callback functions that are registered for that event). If nothing is in the event queue, then the JS interpreter has free time (garbage collection or idle) until some external agent puts something else in the event queue and wakes it up again.

Because all outside events go through the event queue and no event is ever triggered while javascript is actually running something else, it stays single threaded.

Here are some articles on the details:

Vandusen answered 27/9, 2011 at 21:4 Comment(11)
Thanks for that. I suspected this was the case, but good to know for sure. I have a for loop, wherein I send out lots of 'ajax' requests. In my handler (for each request--returned in arbitrary order) I run some code that may take some time. Good to know this should definitely work.Jerome
Do I understand the references correctly that the event loop is a FIFO? So are the events executed in the same order they are added to the event queue? Further, as read in the W3 spec, it is possible that a browser context (tab, iframe etc.) can have several task queues. Is it therefore possible that different kinds of events (e.g. ajax, timeout function) are put into different queues and therefore not executed in the same order they are traversed in the code? The spec simply says: "Run the oldest task on one of the event loop's task queues".Ornis
@Ornis - events are run in FIFO order (it's possible there are some edge-case exceptions, but the intent is FIFO). Some events are treated slightly differently. For example mousemove events don't pile up in the queue (probably because they could easily overflow the queue). When the mouse moves and a mousemove event is in the queue already and there are no other newer events in the queue, it is updated with the latest position rather than a new event added. I would guess that interval timer events are probably also treated specially to avoid them piling up in the queue.Vandusen
@Vandusen - Thank you for the fast response. You don't know any resources which specify or explain this in detail, do you? Apart from browser source code I mean :)Ornis
@Ornis - what do you need explained further? It's FIFO. I added a few more reference articles to my answer. The only execptions to FIFO that I'm aware of are immediately triggered events. You call .focus() on an item and that triggers a couple other events such as a "blur" event on the item with focus. That blur event happens synchronously and doesn't go through the event queue so it would happen right away before other things that might be in the event queue. In practice, I've never found this to be a practical concern.Vandusen
Thank you for the further references. What I am not sure about, how browsers handle several task queues. So adding a timeout to task queue 1 and an ajax response to task queue 2, which task queue will serve the next item to process? But as your references show this is not specified and seems to be browser dependent. Some of the authors of your references say that they are not sure about such details. So digging into browser source code seems to be the only way. Thank you again!Ornis
@Ornis - There aren't multiple queues per browser document. There's one queue and everything goes serially FIFO in/out. So timeouts and ajax responses and mouse events and keyboard events all go in the same queue. Whichever one got put in the queue first gets run first.Vandusen
This , link provides very good explanation of Event Loop.Jennee
@CleanCrispCode - Thx. I added it as a useful reference to my answer.Vandusen
I think this answer would read better if it didn't use the term "thread of execution" which may confuse readers.Angelus
@alnitak - any suggestions on what to use instead?Vandusen
S
16

You can find here a very complete documentation on events handling in javascript.
It is written by a guy working on the javascript implementation in the Opera Browser.

More precisely, look at the titles: "Event Flow", "Event Queuing" and "Non-user Events": you'll learn that:

  1. Javascript runs in a single thread for each browser tab or window.
  2. Events are queued and executed sequentially.
  3. XMLHttpRequest are run by the implementation and callbacks are run using the event queue.

Note: Original link was: link, but is now dead.

Schelling answered 5/10, 2011 at 14:33 Comment(0)
M
2

I want to elaborate a bit, regarding the ajax Implementation mentioned in answers.

Although (regular) Javascript execution is not multi-threaded - as noted well in the above answers - however, the real handling of the AJAX responses (as well as the request handling) is not Javascript, and it - usually - is multi-threaded. (see chromium source implementation of XMLHttpRequest which we'll discus above)

and I'll explain, let's take the following code:

var xhr = new XMLHttpRequest();

var t = Date.now;
xhr.open( "GET", "https://swx.cdn.skype.com/shared/v/1.2.15/SkypeBootstrap.min.js?v="+t(), true );

xhr.onload = function( e ) {
		console.log(t() + ': step 3');
    
    alert(this.response.substr(0,20));
};
console.log(t() + ': step 1');
xhr.send();
console.log(t() + ': step 2');

after an AJAX request is made (- after step 1), then while your js code proceeds executing (step 2 and after), the browser starts the real work of: 1. formatting a tcp request 2. opening a socket 3. sending headers 4. handshaking 5. sending body 6. waiting response 7. reading headers 8. reading body etc. all of this implementation is usually run's in a different thread in parallel to your js code execution. for an example, chromium implementation mentioned uses ThreadableLoader go digg-into 😉, (you can also get some impression by looking at network tab of a page load, you'll see some simultaneous requests).

in conclusion, I would say that - at least - most of your I/O operations can be made simultaneously/async (and you can take advantage of this using an await for example). but all interaction with those operations (the issuing, the js callback execution) are all synchronous.

Mitziemitzl answered 7/3, 2019 at 14:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.