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.
Related
I want to understand internal working of node.js, I am intentionally including computation task ( for loop). But I see it is still blocking main thread.
Here is my script
console.log("start");
for (let i = 0; i < 10; i++) {
console.log(i)
}
console.log("end")
And the o/p is :
start
1
2
3
....
10
end
But according to node.js architecture shouldn't high computation tasks be executed by different thread picked from thread pool and event loop continue executing non-blocking task?
I am referencing node.js internal architecture using this link enter link description here
Can someone please explain the architecture and behavior of the script?
By default, nodejs uses only ONE thread to run your Javascript with. That means that (unless you engage WorkerThreads which are essentially an entirely separate VM), only one piece of Javascript is ever running at once. Nodejs does not "detect" some long running piece of Javascript and move it to another thread. It has no features like that at all. If you have some long running piece of synchronous Javascript, it will block the event loop and block all other Javascript and all other event processing.
Internal to its implementation, nodejs has a thread pool that it uses for certain types of native code (internal implementations of file I/O and crypto operations). That only supports the implementation of asynchronous implementations for file I/O and crypto operations - it does not parallelize the running of Javascript.
So, your script you show:
console.log("start");
for (let i = 0; i < 10; i++) {
console.log(i)
}
console.log("end")
Is entirely synchronous and runs sequentially and blocks all other Javascript from running while it is running because it is using the one thread for running Javascript while it is running.
Nodejs gets its excellent scalability from its asynchronous I/O model that does not have to use a separate thread in order to have lots of asynchronous operations in flight at the same time. But, keep in mind that these asynchronous I/O operations all have native code behind them (some of which may use threads in their native code implementations).
But, if you have long running synchronous Javascript operations (like say something like image analysis written in Javascript), then those typically need to be moved out of the main event loop thread either by shunting them off to WorkerThreads or to other processes or to a native code implementation that may use OS threads.
But according to node.js architecture shouldn't high computation tasks be executed by different thread picked from thread pool and event loop continue executing non-blocking task?
No, that is not how nodejs works and is not a correct interpretation of the diagram you show. The thread pool is NOT used for running your Javascript. It is used for internal implementation of some APIs such as file I/O and some crypto operations. It is not used for running your Javascript. There is just one main thread for running your Javascript (unless you specifically run your code in a WorkerThread).
I want to understand internal working of node.js, I am intentionally including computation task ( for loop). But I see it is still blocking main thread.
Yes, a for loop (that does not contain an await statement that is awaiting a promise) will completely occupy the single Javascript thread and will block the event loop from processing other events while the for loop is running.
JS executes its code Synchronouse. there are few things that gets "Asynchronouse" like setInterval or setTimout for exmple. But thats actually not fully true. Asynchronouse means things get done in parallel witch is not true. Take a look at setTimeout. By executing it you add the function into the task que, later the event loop grabs it from the que and put it onto the stack and executes it, syncrhonouse. If you want to execute something really parallel then you should consider using an worker thread
There are absolutely no threads in JS (unless you explicitly use worker threads). Javascript uses cooperative multi-tasking which means that a function will always complete before the next one will start. The only other way to yield control back to the scheduler is to separate a task out into another function that is called asynchronously. So in your example, e.g., you could do:
console.log("start");
setTimeout(() => {
for (let i = 0; i < 10; i++) {
console.log(i)
}}, 0);
console.log("end")
and you would get:
start
end
1
2
..
9
This also answers your question about heavy computations: unless you use the relatively new worker threads, you cannot run heavy computations in node.js "in the background" without the use of native code.
So if you really have heavy loads you have three options:
worker threads,
native code that is multi-threaded, e.g., written in C/C++, or
breaking your computation down into small pieces, each one yielding control back to the scheduler when done (e.g., using map/reduce).
I just read an article about the event loop in JavaScript.
I found two contradictive phrases and I would be glad if someone could clarify.
A downside of this model is that if a message takes too long to
complete, the web application is unable to process user interactions
like click or scroll. The browser mitigates this with the "a script is
taking too long to run" dialog
A very interesting property of the event loop model is that
JavaScript, unlike a lot of other languages, never blocks. Handling
I/O is typically performed via events and callbacks, so when the
application is waiting for an IndexedDB query to return or an XHR
request to return, it can still process other things like user input
So, when is the first one true and when is the second one true?
"A very interesting property of the event loop model is that
JavaScript, unlike a lot of other languages, never blocks.
This is misleading. Without clever programming, JavaScript would always block the UI thread, because runtime logic always blocks the UI, by design. At a smooth sixty frames a second, that means your application logic must always cooperatively yield control (or simply complete execution) within about 16 milliseconds, otherwise your UI will freeze or stutter.
Because of this, most JavaScript APIs that might take a long time (eg. network requests) are designed in such a way to use techniques (eg callbacks, promises) to circumvent this problem, so that they do not block the event loop, avoiding the UI becoming unresponsive.
Put another way: host environments (eg a Web browser or a Node.js runtime instance) are specifically designed to enable the use of an event-based programming model (originally inspired by programming environments like Hypercard on the Mac) whereby the host environment can be asked to perform a long-running task (eg run a timer), without blocking the main thread of execution, and for your program to be notified later, via an "event" when the long-running task is complete, enabling your program to pick-up where it left-off.
Both are correct, even though I agree it is somewhat wrongly expressed.
So by points:
It's true that if a synchronous task takes too long to complete, the event loop "gets stuck" there and then all other queued tasks can't run till it finishes.
Here it is talking about asynchronous tasks so even though an HTTP request, an I/O request or whatever that is async takes too long to process, all the synchronous tasks can keep doing their job, like processing user input
There are two types of code inside Javascript
Synchronous (it's like going one by one).
Asynchronous (it's like skipping for the future)
Synchronous code
You want to find the prime number from 1 to 10000000 with synchronous code you will write a function and that function will perform the calculation and finds out the prime number in the given range but what will happen with synchronous code. The javascript engine is not able to do any task until that task gets finished.
Asynchronous Code
If you wrap the same code inside a callback or more friendly with the SetTimeout method the javascript put that function inside the event queue and perform the other operation when a certain time came the timeout method fires callback certainly when there is nothing inside the call stack, it will ask event loop to pass the first thing which is inside the event queue. So this more about finding an idle time to perform the heavy operation.
Use javascript workers to perform heavy mathematics tasks not
SetTimeout because eventually, it will block the engine when the
function is inside the call stack.
I went through the link below and understood single threaded javascript and its asynchronous nature a little
https://www.sohamkamani.com/blog/2016/03/14/wrapping-your-head-around-async-programming/
But I still have questions that javascript is single threaded and it always moves in forward direction in sequential manner until it finishes its execution.
Whenever we made call to function which has a callback, that callback will be executed after function receives response. Execution of javascript code continues during the wait time for the response. In this way where execution happening in sequence how callback execution will be resumed once after response received. It's like thread is moving backwards for callback execution.
Thread of execution should always move in forward direction righy?.
please clarify on this.
It's true that JavaScript is (now) specified to have only a single active thread per realm (roughly: a global environment and its contents).¹ But I wouldn't call it "single-threaded;" you can have multiple threads via workers. They do not share a common global environment, which makes it dramatically easier to reason about code and not worry about the values of variables changing out from under you unexpectedly, but they can communicate via messaging and even access shared memory (with all the complications that brings, including the values of shared memory slots changing out from under you unexpectedly).
But running on a single thread and having asynchronous callbacks are not at all in conflict. A JavaScript thread works on the basis of a job queue that jobs get added to. A job is a unit of code that runs to completion (no other code in the realm can run until it does). When that unit of code is done running to completion, the thread picks up the next job from the queue and runs that. One job cannot interrupt another job. Jobs running on the main thread (the UI thread in browsers) cannot be suspended in the middle (mostly²), though jobs on worker threads can be (via Atomics.wait). If a job is suspended, no other job in the realm will run until that job is resumed and completed.
So for instance, consider:
console.log("one");
setTimeout(function() {
console.log("three");
}, 10);
console.log("two");
When you run that, you see
one
two
three
in the console. Here's what happened:
A job for the main script execution was added to the job queue
The main JavaScript thread for the browser picked up that job
It ran the first console.log, setTimeout, and last console.log
The job terminated
The main JavaScript thread idled for a bit
The browser's timer mechanism determined that it was time for that setTimeout callback to run and added a job to the job queue to run it
The main JavaScript thread picked up that job and ran that final console.log
If the main JavaScript thread were tied up (for instance, while (true);), jobs would just pile up in the queue and never get processed, because that job never completes.
¹ The JavaScript specification was silent on the topic of threading until fairly recently. Browsers and Node.js used a single-active-thread-per-realm model (mostly), but some much less common environments didn't. I vaguely recall an early fork of V8 (the JavaScript engine in Chromium-based browsers and Node.js) that added multiple threading, but it never went anywhere. The Java virtual machine can run JavaScript code via its scripting support, and that code is multi-threaded (or at least it was with the Rhino engine; I have no ideal whether Narwhal changes that), but again that's quite niche.
² "A job is a unit of code that runs to completion." and "Jobs running on th emain thread...cannot be suspended in the middle..." Two caveats here:
alert, confirm, and prompt — those 90's synchronous user interactions — suspend a job on the main UI thread while waiting on the user. This is antiquated behavior that's grandfathered in (and is being at least partially phased out).
Naturally, the host process — browser, etc. — can terminate the entire environment a job is running in while the job is running. For instance, when a web page becomes "unresponsive," the browser can kill it. But that's not just the job, it's the entire environment the job was running in.
Just to add to T.J.Crowder’s answer above:
The job queue is called an Event Loop which keeps track of all the callbacks that need to be executed. Whenever a callback is ready to be executed ( example: after an asynchronous action has finished ), it is added in the Event loop.
As explained by T.J. Crowder, you can imagine Event loop as a queue. Whenever there is a callback to execute in the loop, the loop takes control of the main thread and executes that callback. The execution of the normal flow stops while this is happening. This way JavaScript can be imagined as a single-threaded language.
You can learn more about Event Loops and how they work in this amazing talk by Philip Roberts.
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.
Greetings,
I've been studying javascript, nodejs. And I don't understand how the concurrency issues are avoided in javascript.
Lets say I'm working on a object
var bigObject = new BigObject();
and I have a setTimer(function(){ workOnBigOjbect...} ) that will also do work on bigOjbect.
If I have disk IO being written into bigObject, and a timer object working on bigObject, and regularly code reading from bigObject, how are concurrency issues avoided?
In a regular language, I would use a mutex or thread-safe queue/command pattern. I also don't see much discussion about race conditions for javascript.
Am I missing something?
The whole point of node.js is that it's event-driven. All the code runs in event handlers in a single thread. There are no concurrency issues because the code doesn't run concurrently. The downside is that each event handler must exit quickly because it blocks the other events.
In your example, the code will start the disk IO and exit immediately. The node.js infrastructure will notify the program that the IO operation was completed by running an event handler. The timer event will be called before or after the IO event, but never concurrently.
Javascript is single-threaded. If the time arrives when your function is supposed to execute (based on how you called setTimer), and the parent code is still running, the function will not execute until the parent code has completed.
There is only a single thread; see: Node.js on multi-core machines
I would speculate that this is because Multiple threads are not supported in the underlying V8 JavaScript engine since typically JavaScript executes within a browser (where in a windows case there is only a single UI thread) and does not support multiple threads.
There's is this thing in javascript called Run-to-Completion which ensures that if a code is executing it executes completely before any other (asynchronous) code runs, hence, no concurrency issues.
In case of your example whenever the timer callback is called it will execute completely and will never be pre-empted in middle to execute some other code.
See Why no concurrency control tool in javascript for more details.