This question already has answers here:
How does JavaScript handle AJAX responses in the background?
(3 answers)
Closed 5 years ago.
I know javascript runs on single thread. I also, know when we make an async ajax call using jquery, the code does not stop and continues execution serially. The response is handled by the callback. My question is how does the single thread does this? Does the thread handles the callback & stop the further code execution when we get the response back?
No, it does not stop code execution.
The callback gets queued and when there is nothing else to execute, it will be run.
No two things happen at the same time, and scheduling is not pre-emptive.
So if you keep your single thread busy with things like infinite loops, the callback will never get a chance to run.
The browser manages an event queue. When an event occurs, such as a response arriving from an Ajax call, a timer firing, or a mouse or touch event, the appropriate callback is being called on the main thread, when it is idle.
This is not exsactly how it works as it depends on if you are using Node or a browser and which browser but it is a good mental model.
JavaScript is laying on top of another language like C which is multi threaded. When JavaScript runs a ajaxs request it will add the request to a queue and the language built to handle the network request will do it. When the request is done it changes the value in the queue.
After every process cycle JavaScript will check this queue and run any callbacks linked to the completed tasks. So JavaScript does not do the process itself but just checks when they are done.
Related
I am learning Node.js and some javascript. I read up some stuff of thinks like queues and execution stacks.
I am trying to calculate time taken by a websocket request to complete. A very typical emit is of form:
microtime1 = getTimeNow;
socket.emit("message","data", function (error, data) {
// calculate time taken by using microtime module by getting updated time and calculating difference.
microtime2 = getTimeNow;
time = microtime2 - microtime1;
})
If I am sending multiple messages, can I rely on callback getting executed without delay or can there be a hold up in the queue and callback won't get executed.
In other words, would callback only get called once it's in stack or does it get executed while it's waiting to be picked up in the queue ?
Hope, I was able to explain my question.
In other words, would callback only get called once it's in stack or does it get executed while it's waiting to be picked up in the queue ?
The callback gets executed after the event, that it is waiting for, is resolved.
So the callback should work just fine, however there is a caveat. because node-js is single threaded, you could have another process that's blocked the main thread.
For example the simple view of execution may look like this. One event is processed, and then another one is processed after.
However, in reality it may look more like this
The single thread is meant for the main thread only, things like the IO operations are done on another dedicated thread that will notify main thread when it's done, and then the callback can be executed after
The problem occurs if your main thread becomes busy while waiting for the network action to complete
This is hard to predict though and depends on what the rest of the app is doing. If your app is not doing anything else, this likely won't be an issue. But, IMHO, a better way is to make hundreds or thousands of calls and allow get an average which will account for other possible causes for discrepancies in the delta.
Additional data from c-sharpcorner.com
The above diagram shows the
execution process of Node.js. Let's understand it step by step.
Step 1
Whenever a request comes to Node.js API, that incoming request is
added to the event queue. This is because Node.js can't handle
multiple requests simultaneously. The first time, the incoming request
is added to the event queue.
Step 2
Now, you can see in the diagram that one loop is there which always
checks if any event or request is available in event queue or not. If
any requests are there, then according to the "First Come, First
Served" property of queue, the requests will be served.
Step 3
This Node.js event loop is single threaded and performs non blocking
i/o tasks, so it sends requests to C++ internal thread pool where lots
of threads can be run. This C++ internal thread pool is the part of
event loop developed in Libuv. This can handle multiple requests. Now,
event loop checks again and again if any event is there in the Event
Queue. If there is any, then it serves to the thread pool if the
blocking process is there.
Step 4
Now, the internal thread pool handles a lot of requests, like database
request, file request, and many more.
Step 5
Whenever any thread completes that task, the callback function calls
and sends the response back to the event loop.
Step 6
Now, event loop sends back the response to the client whose request is
completed.
I was just reading an article about asynchronous programming and the event loop. During the read he describes that if I call an asynchronous method and pass it a callback, e.g. an Ajax request, the web API will deal with an event. The event in this case would be the Ajax request receiving a message. When the event is raised it is added to the event queue and when the call stack is empty and the event queue are being called, the callback from the event is called.
Given that the callback of the event queue is placed onto the call stack, which is on the UI thread, would that not mean that having a substantially long callback would result in the UI being blocked? Was asynchronous programming not meant to prevent these types of problems?
Edit: I just realized I could test my theory by opening the browser and testing it myself by creating,
setTimeout(function(){
while(true){}
}, 500)
When typing this, the UI will freeze.
Does this imply I am correct? An asynchronous call and asynchronous code can still freeze the UI?
Yes, your intuition is correct.
Because javascript is single-threaded, any work done during a turn of the event loop will block the UI.
The advantage of async calls like Ajax, is that your script doesn't actually need to do any work while it waits for a network response. It is better to yield control while waiting, freeing the UI until the Ajax call comes back and then you can do something.
As an example, you can send an Ajax request in sync mode, and it will block while waiting
Asynchronous code will eventually execute on main thread. So while the asynchronous code will be executing on main thread, main thread will freeze. That means no other code can run. Asynchronous code will not start to execute right away. It will wait until it's time has come, and when the time comes for the asynchronous code to execute it will execute in synchronous manner.
Let me come to the example you have provided.
setTimeout(function(){
while(true){}
}, 500)
The callback you have provided to setTimeout will not execute before 500 millisecond have passed. When the waiting time will over, javascript engine will load the callback function to main thread for executing. As it is an infinite loop, main thread will be blocked for infinite amount of time. No other code will have any chance to be executed.
This question already has answers here:
How the single threaded non blocking IO model works in Node.js
(9 answers)
Closed 3 years ago.
Node js is a single-threaded application even though it executes the asynchronous operation my initial understanding about this was like this
“The Event loop runs in a separate thread in the user code. There is a main thread where the JavaScript code of the user (userland code) runs in and another one that runs the event loop. Every time an asynchronous operation takes place, the main thread will hand over the work to the event loop thread and once it is done, the event loop thread will ping the main thread to execute a callback.” And this article explains to me it is wrong. https://www.freecodecamp.org/news/walking-inside-nodejs-event-loop-85caeca391a9/
Also, I have seen that there is some code return result after the first part is executed even though that part is called after the first part. I am getting terribly confused here can someone is able to help me with this?
Also what is libuv has to do with this?
Single thread means event queue runs in a single thread. In the background there are other threads that runs jobs like IO. There is a thread pool for them but you are not interested in the internals of that as a developer. That simplifies handling of the blocking IO tasks for the application developer. You just send a request and register for the result of your task and run your code in the callback.
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?
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:
How Javascript Timers Work - written by John Resig
Events and Timing in Depth
W3 spec: HTML5 event loops
MDN article on Event Loop
Presentation on JS event queue
The JavaScript Event Loop: Explained
Five Patterns to Help Tame Asynchronous Javascript
Javascript Event Loop Presentation
Video Discussing How Javascript Works (including event loop at 10:27)
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:
Javascript runs in a single thread for each browser tab or window.
Events are queued and executed sequentially.
XMLHttpRequest are run by the implementation and callbacks are run using the event queue.
Note: Original link was: link, but is now dead.
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.
I am thinking about it and this is what I came up with:
Let's see this code below:
console.clear();
console.log("a");
setTimeout(function(){console.log("b");},1000);
console.log("c");
setTimeout(function(){console.log("d");},0);
A request comes in, and JS engine starts executing the code above step by step. The first two calls are sync calls. But when it comes to setTimeout method, it becomes an async execution. But JS immediately returns from it and continue executing, which is called Non-Blocking or Async. And it continues working on other etc.
The results of this execution is the following:
a c d b
So basically the second setTimeout got finished first and its callback function gets executed earlier than the first one and that makes sense.
We are talking about single-threaded application here. JS Engine keeps executing this and unless it finishes the first request, it won't go to second one. But the good thing is that it won't wait for blocking operations like setTimeout to resolve so it will be faster because it accepts the new incoming requests.
But my questions arise around the following items:
#1: If we are talking about a single-threaded application, then what mechanism processes setTimeouts while the JS engine accepts more requests and executes them? How does the single thread continue working on other requests? What works on setTimeout while other requests keep coming in and get executed.
#2: If these setTimeout functions get executed behind the scenes while more requests are coming in and being executed, what carries out the async executions behind the scenes? What is this thing that we talk about called the EventLoop?
#3: But shouldn't the whole method be put in the EventLoop so that the whole thing gets executed and the callback method gets called? This is what I understand when talking about callback functions:
function downloadFile(filePath, callback)
{
blah.downloadFile(filePath);
callback();
}
But in this case, how does the JS Engine know if it is an async function so that it can put the callback in the EventLoop? Perhaps something like the async keyword in C# or some sort of an attribute which indicates the method JS Engine will take on is an async method and should be treated accordingly.
#4: But an article says quite contrary to what I was guessing on how things might be working:
The Event Loop is a queue of callback functions. When an async
function executes, the callback function is pushed into the queue. The
JavaScript engine doesn't start processing the event loop until the
code after an async function has executed.
#5: And there is this image here which might be helpful but the first explanation in the image is saying exactly the same thing mentioned in question number 4:
So my question here is to get some clarifications about the items listed above?
1: If we are talking about a single-threaded application, then what processes setTimeouts while JS engine accepts more requests and executes them? Isn't that single thread will continue working on other requests? Then who is going to keep working on setTimeout while other requests keep coming and get executed.
There's only 1 thread in the node process that will actually execute your program's JavaScript. However, within node itself, there are actually several threads handling operation of the event loop mechanism, and this includes a pool of IO threads and a handful of others. The key is the number of these threads does not correspond to the number of concurrent connections being handled like they would in a thread-per-connection concurrency model.
Now about "executing setTimeouts", when you invoke setTimeout, all node does is basically update a data structure of functions to be executed at a time in the future. It basically has a bunch of queues of stuff that needs doing and every "tick" of the event loop it selects one, removes it from the queue, and runs it.
A key thing to understand is that node relies on the OS for most of the heavy lifting. So incoming network requests are actually tracked by the OS itself and when node is ready to handle one it just uses a system call to ask the OS for a network request with data ready to be processed. So much of the IO "work" node does is either "Hey OS, got a network connection with data ready to read?" or "Hey OS, any of my outstanding filesystem calls have data ready?". Based upon its internal algorithm and event loop engine design, node will select one "tick" of JavaScript to execute, run it, then repeat the process all over again. That's what is meant by the event loop. Node is basically at all times determining "what's the next little bit of JavaScript I should run?", then running it. This factors in which IO the OS has completed, and things that have been queued up in JavaScript via calls to setTimeout or process.nextTick.
2: If these setTimeout will get executed behind the scenes while more requests are coming and in and being executed, the thing carry out the async executions behind the scenes is that the one we are talking about EventLoop?
No JavaScript gets executed behind the scenes. All the JavaScript in your program runs front and center, one at a time. What happens behind the scenes is the OS handles IO and node waits for that to be ready and node manages its queue of javascript waiting to execute.
3: How can JS Engine know if it is an async function so that it can put it in the EventLoop?
There is a fixed set of functions in node core that are async because they make system calls and node knows which these are because they have to call the OS or C++. Basically all network and filesystem IO as well as child process interactions will be asynchronous and the ONLY way JavaScript can get node to run something asynchronously is by invoking one of the async functions provided by the node core library. Even if you are using an npm package that defines it's own API, in order to yield the event loop, eventually that npm package's code will call one of node core's async functions and that's when node knows the tick is complete and it can start the event loop algorithm again.
4 The Event Loop is a queue of callback functions. When an async function executes, the callback function is pushed into the queue. The JavaScript engine doesn't start processing the event loop until the code after an async function has executed.
Yes, this is true, but it's misleading. The key thing is the normal pattern is:
//Let's say this code is running in tick 1
fs.readFile("/home/barney/colors.txt", function (error, data) {
//The code inside this callback function will absolutely NOT run in tick 1
//It will run in some tick >= 2
});
//This code will absolutely also run in tick 1
//HOWEVER, typically there's not much else to do here,
//so at some point soon after queueing up some async IO, this tick
//will have nothing useful to do so it will just end because the IO result
//is necessary before anything useful can be done
So yes, you could totally block the event loop by just counting Fibonacci numbers synchronously all in memory all in the same tick, and yes that would totally freeze up your program. It's cooperative concurrency. Every tick of JavaScript must yield the event loop within some reasonable amount of time or the overall architecture fails.
Don't think the host process to be single-threaded, they are not. What is single-threaded is the portion of the host process that execute your javascript code.
Except for background workers, but these complicate the scenario...
So, all your js code run in the same thread, and there's no possibility that you get two different portions of your js code to run concurrently (so, you get not concurrency nigthmare to manage).
The js code that is executing is the last code that the host process picked up from the event loop.
In your code you can basically do two things: run synchronous instructions, and schedule functions to be executed in future, when some events happens.
Here is my mental representation (beware: it's just that, I don't know the browser implementation details!) of your example code:
console.clear(); //exec sync
console.log("a"); //exec sync
setTimeout( //schedule inAWhile to be executed at now +1 s
function inAWhile(){
console.log("b");
},1000);
console.log("c"); //exec sync
setTimeout(
function justNow(){ //schedule justNow to be executed just now
console.log("d");
},0);
While your code is running, another thread in the host process keep track of all system events that are occurring (clicks on UI, files read, networks packets received etc.)
When your code completes, it is removed from the event loop, and the host process return to checking it, to see if there are more code to run. The event loop contains two event handler more: one to be executed now (the justNow function), and another within a second (the inAWhile function).
The host process now try to match all events happened to see if there handlers registered for them.
It found that the event that justNow is waiting for has happened, so it start to run its code. When justNow function exit, it check the event loop another time, searhcing for handlers on events. Supposing that 1 s has passed, it run the inAWhile function, and so on....
The Event Loop has one simple job - to monitor the Call Stack, the Callback Queue and Micro task queue. If the Call Stack is empty, the Event Loop will take the first event from the micro task queue then from the callback queue and will push it to the Call Stack, which effectively runs it. Such an iteration is called a tick in the Event Loop.
As most developers know, that Javascript is single threaded, means two statements in javascript can not be executed in parallel which is correct. Execution happens line by line, which means each javascript statements are synchronous and blocking. But there is a way to run your code asynchronously, if you use setTimeout() function, a Web API given by the browser, which makes sure that your code executes after specified time (in millisecond).
Example:
console.log("Start");
setTimeout(function cbT(){
console.log("Set time out");
},5000);
fetch("http://developerstips.com/").then(function cbF(){
console.log("Call back from developerstips");
});
// Millions of line code
// for example it will take 10000 millisecond to execute
console.log("End");
setTimeout takes a callback function as first parameter, and time in millisecond as second parameter.
After the execution of above statement in browser console it will print
Start
End
Call back from developerstips
Set time out
Note: Your asynchronous code runs after all the synchronous code is done executing.
Understand How the code execution line by line
JS engine execute the 1st line and will print "Start" in console
In the 2nd line it sees the setTimeout function named cbT, and JS engine pushes the cbT function to callBack queue.
After this the pointer will directly jump to line no.7 and there it will see promise and JS engine push the cbF function to microtask queue.
Then it will execute Millions of line code and end it will print "End"
After the main thread end of execution the event loop will first check the micro task queue and then call back queue. In our case it takes cbF function from the micro task queue and pushes it into the call stack then it will pick cbT funcion from the call back queue and push into the call stack.
JavaScript is high-level, single-threaded language, interpreted language. This means that it needs an interpreter which converts the JS code to a machine code. interpreter means engine. V8 engines for chrome and webkit for safari. Every engine contains memory, call stack, event loop, timer, web API, events, etc.
Event loop: microtasks and macrotasks
The event loop concept is very simple. There’s an endless loop, where the JavaScript engine waits for tasks, executes them and then sleeps, waiting for more tasks
Tasks are set – the engine handles them – then waits for more tasks (while sleeping and consuming close to zero CPU). It may happen that a task comes while the engine is busy, then it’s enqueued. The tasks form a queue, so-called “macrotask queue”
Microtasks come solely from our code. They are usually created by promises: an execution of .then/catch/finally handler becomes a microtask. Microtasks are used “under the cover” of await as well, as it’s another form of promise handling. Immediately after every macrotask, the engine executes all tasks from microtask queue, prior to running any other macrotasks or rendering or anything else.