What can go wrong if you make synchronous Ajax calls using jQuery | Understanding event loop in Javascript
Have you ever made synchronous API calls in Javascript?
If you are a Javascript developer, you would know that Javascript is single threaded and blocking main thread is a sin.
What would happen if you make a synchronous Ajax call? jQuery gives us a flag called async
and setting it false will make Ajax request synchronous.
$.ajax({
url: '<URL>',
method: 'get',
async: false, // notice this line
success: () => {}
});
Synchronous API call means Javascript thread will stop further execution of code until this Ajax request gets resolved. Since the main thread is blocked waiting for request to get completed, your browser will stop responding to events (it will become unresponsive). I know what are you thinking, why on earth would someone do that?
Let’s say that I am a naive developer and I want to make synchronous API call. I really need API data before rendering UI so I don’t care if my page is unresponsive for 1 or 2 secs. However I do want to show a loader till the time API request gets resolved. My code would look something like this-
Do you see a problem in this code?
At first glance everything looks fine. I have defined two functions- showLoader and hideLoader to show and hide loader element. Inside an IIFE (immediately invoked function expression), I call showLoader function first, make an Ajax call synchronously and then call hideLoader function. Since the API call is synchronous, hideLoader function will only be called once I get API response so I should be able to see loader during that period of time.
The only problem is, I am not able to see loader at all. Don’t believe me? Look by yourself-
Hmm, so what’s really happening here?
If you are thinking that this weird behaviour has to do something with jQuery or Ajax call then you are wrong! Even if I mock API call with loop that will run for 2 secs, I still get the same behaviour.
Did you figure it out?
Let me give you a hint. If I put the loop (or synchronous Ajax call) inside a setTimeout function, I am able to see initial loader for 2 secs.
This the outcome of above code-
Event loop in Javascript
You must have got it by now. The answer lies in how Event loop handles task (callback) and render queue.
Whenever Javascript call stack is empty, event loop will keep monitoring task queue as well as render queue. Render queue has highest priority and it is used to paint pixels on the screen. It transforms HTML, CSS and JS code into raster images to show to the end user. Task/Callback queue on the other hand contains callback functions (setTimeout, event listeners, Ajax callbacks etc) which are pushed to call stack (one by one) by event loop to get executed.
The important thing to note here is that both the queues will be processed only when main call stack is empty. In our example when we are not using setTimeout, code will be executed synchronously and main thread will be blocked. Even though loader DOM element gets modified (display: block), event loop does not get chance to process render queue. When loop ends or API call gets resolved, loader CSS property is also changed (display: none) so in next render loader is still invisible.
In the latter case when we are using setTimeout, whole API call (or loop) gets pushed to callback/task queue and main thread gets empty. This allows event loop to process render queue (because it has higher priority than callback queue) and hence loader is visible.
Conclusion
Javascript is a unique programming language in many way and learning it is always a fun.
Hope you enjoyed this article :)