Consider the following piece of code:
var some_expensive_task = function(i) {
setTimeout(function() {
var a = 1;
while (a < 100000000) {
Math.sqrt(a);
++a;
}
console.log('finished set' + i);
}, 0);
};
for (var i = 0; i < 70; ++i) {
console.log('start ' + i);
some_expensive_task(i);
console.log('end ' + i);
}
The intent of this program was to iterate over and start 70 cpu intensive asynchronous tasks using setTimeout.
As expected, the output of this program is:
start 1
end 1
...
start 69
end 69
finished set1
...
finished set69
Throughtout the entire execution, there were only two processes. One of which I assume was the idle event loop and the other was the worker process running at 100%.
Am I correct in understanding that while the event loop is executed synchronously, asynchronous tasks that are started, regardless of origin, are executed synchronously in the order that they were called?
UPDATE
I still don't feel as if I've conveyed my question clear enough. Using setTimeout was the only way I could think of to accurately schedule a bunch of async functions to run. I guess the real question is, if I start three async functions with setTimeout, still with a zero delay, is the second one I start guaranteed to run after the first one finishes and is the third one guaranteed to start after the second one finishes?
You use incorrect terminology in the question, Are Node.js asynchronous tasks handled synchronously does not make much sense. And the test case is not what you think it is. First making clear some terminologies:
Synchronous functions are guaranteed to run/complete in the order of their invocation.
Asynchronous functions can progress and complete out-of-order w.r.to their calling.
Blocking operations are those operations which once started must complete for the execution to progress further. CPU-intensive operations are blocking unless you run them on a separate worker. loops are blocking in nature. Once they start, they will complete all iterations before next function is executed.
setTimeout simply calls the passed function at least x ms after current time. Calling it means once x ms pass it queues the passed function on the event loop. It is just delayed execution.
So considering above facts, here is why your test is misleading:
First your test case (your CPU-intensive function) is not asynchronous, you wrapped it around a setTimeout which is asynchronous. The timeout of 0 simply implies that they will be executed in the same order they are called. All callback functions being synchronous.
Second, start and end in the log indicates point where your setTimeout is called. This would be in-order as expected. With timeout 0, the completion will be in-order too. Yes if you keep timeout equal for them they all will be executed in the same order as passed. Then again this is one of many possible cases where outcome is similar to synchronous (what if timeouts were in increasing order?). What you asked may be true for these cases but not always.
Third if you wanted to simulate asynchronicity (enough to see out-of-order behaviour on console), might as well loose the while loop and use random timeouts(Math.random()*1000). You will see they complete in arbitrary fashion. This would be asynchronous execution (of setTimeout not the callback).
Node.js is single threaded and runs in one process because JavaScript is single threaded. Thus you are correct.
Yes. Javascript, including NodeJS, is single threaded (with a few exceptions).
When you use setTimeout(fn, 0), it queues up the function to run after the current call stack has cleared. In your example, that means that the for loop will complete before the "expensive tasks" get run.
Your JS code runs in a single thread in Node.js. All other native Node.js API are written in C/C++ and are either asynchronous or run on a separate thread.
See this answer for the more detailed explanation.
Am I correct in understanding that while the event loop is executed synchronously, asynchronous tasks that are started, regardless of origin, are executed synchronously in the order that they were called?
Yes, you are correct.
Related
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.
I have this code:
console.log('1');
process.nextTick(() => console.log('inside nextTick'));
setImmediate(()=> console.log('inside setImmediate'));
console.log("2");
for(var i=0;i<1 ; i++) {
console.log("inside for loop");
}
And output is:
1
2
inside for loop
inside nextTick
inside setImmediate
Please explain why it is happening. Even if I have written console.log("2"); and the for loop after process.nextTick and setImmediate, why are they executing before them?
That's how asynchronous code works in JavaScript. When you schedule asynchronous code, it's added to the event queue. This is processed by the main event loop, which only gets control when synchronous code returns. So all the synchronous code runs, which logs all those message, then it returns to the main event loop, which invokes all the asynchronous tasks.
Asynchronous is a behaviour, if we have two lines of code Line-1 followed by Line-2. Line-1 is a time-consuming instruction. So Line-1 starts executing its instruction in the background (like a daemon process), allowing Line-2 to start executing without having to wait for Line-1 to finish.
We need this behaviour when things are slow. Synchronous executions of code may seem straightforward but can be slow. Tasks like image processing can be slow, file operations can be really slow, making network request and waiting for response is definitely slow, making huge calculations like over a 100 million for-loop iteration is somewhat slow. So such slow things in Call stack results in “Blocking”. When call stack is blocked, the browser prevents user’s interrupts and other code statements from executing until the blocking statement is executed and the call stack is freed. Hence Asynchronous callbacks are used to handle such situations.
ex:
console.log("Hello");
setTimeout(function(){ console.log("Susi");},2000);
console.log("Iam");
o/p: Hello, Iam susi.
In your example first it will print the console statements because process.next will execute in the next iteration of event loop and then setimmediate. due to that your getting the output as below.
1
2
inside for loop
inside nextTick
inside setImmediate
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.
The code below is a nodeJS code. I am new to nodeJS and i am pretty confused with the flow of code in a nodejs since it tells that nodejs is single threaded and in the other hand it also tells us that the callbacks and IO are asynchronous if i am not wrong. Can anyone give me the actual meaning of callbacks and how the code is working. Is it so that the asynchronous function which we are calling as callbacks are executed by some other thread/process and not by the single nodejs thread (P.S-It is the concept what i understood...i may b wrong), then why we r callng nodejs as single threaded program.
function placeOrder(orderNo) {
setTimeout(function() {
deliver(orderNo);
}, 5000);
console.log("Order is: " + orderNo);
}
function deliver(orderNo) {
console.log("Item is delivered with Order No.- " + orderNo);
}
placeOrder(1);
placeOrder(2);
placeOrder(3);
placeOrder(4);
placeOrder(5);
placeOrder(6);
Nodejs is single threaded. There's an event loop that runs continuously and executes whatever instructions it has to execute. So basically when you use the setTimeout function with 5 seconds interval, it will place some code to be executed by the event loop 5 seconds later. Of course if the event loop is busy executing some other code at this time it will postpone the execution of your code for a later stage. So it might not execute 5 seconds later but rather 5.1 seconds later.
So when you call setTimeout(function() { ... }, 5000); you are scheduling some javascript code to execute at least 5 seconds later by the event loop.
Asynchronous is not the same as multi-threaded. In the case above, you're asking for async callbacks, but your single thread listens for those callbacks when it's not running your other code. The callbacks all come back to the same thread that requested them.
You won't get two deliver functions running at the same time because of this. If you sleep inside of deliver, the other callbacks will have to wait. This is why, in single-threaded environments like this, it is important to get the work done fast and return (to the browser or to node) so that the event loop can resume listening for more callbacks on the same thread.
Asynchronous in Nodejs is a definition for general idea of how Nodejs based on.
For details, nodejs is using single thread to run the event loop for handling request (to specify which one is non-blocking IO and which one is blocking IO)
In case the request is non-blocking IO actions. It will be attached callback handler for quickly response. The computation of function, inside function will be handle from the logic of Stack & Heap.
In case the request is blocking IO actions. Nodejs will get one thread of thread pool to handle that request and the program itself will have something called IO waiting time.
"use strict"
const
fs = require('fs'),
stream = fs.createReadStream("file.txt"),
timeout = 0;
stream.on('data', function() {
console.log("File Read");
});
setTimeout(function(){
console.log("setTimeout : " + timeout);
}, timeout);
I'm learning node.js / javascript and I was wondering why is this program returning
setTimeout : 0
File Read
and not the other way around.
Correct me if I'm wrong but in javascript the callback queue is fifo, stacking the stream first and out first?
I think that because of the non-blocking nature of nodejs, both callback are run in "parallel" and setTimeout finishes first and return (for example a timeout of 1000ms would switch the results.)
Correct me if I'm wrong but in javascript the callback queue is fifo,
stacking the stream first and out first?
Not quite. Async callbacks are processed FIFO in the order they complete their operations, not in the order their operations were started. So, the amount of time the operation takes to complete is very important in determining when the callback gets scheduled. Short operations may complete before long operations, even if they were started later.
It takes time to open a file and start reading it and the setTimeout() takes no time so it occurs first. When you have independent asynchronous operations, you can almost never "know" what order they will occur in because it depends upon the internal timing of the various functions.
The readStream operation gets started before the timer gets started, but the timer finishes before the readStream operation gets its first data just due to the amount of work required internally for the two async operations.
I think that because of the non-blocking nature of nodejs, both
callback are run in "parallel" and setTimeout finishes first and
return (for example a timeout of 1000ms would switch the results.)
Yes, this is correct.
Think of it like this. You have two powerful megaphones and a really good microphone. You set up two targets to point the megaphone at and listen for the returned echo. One target ie very close and one target is very far away. You first blast the megaphone at the very far away target, then immediately blast the megaphone at the near target. In no surprise, you get the echo from the near target first even though you sent its blast after the first one, simply because the echo from the far away target takes a lot longer to traverse all its extra distance and get back to you. The same is true of your readStream. Even though you started it first, it takes a lot longer than a setTimeout(fn, 0) so the setTimeout() finishes first and thus calls its callback first.
If the timing is important to you, then you SHOULD use tools like promises to specifically sequence your async operations or to wait until all necessary results are ready. A good design should not "assume" that one async operation will complete before another unless your code specifically guarantees that by sequencing the operations.
It is surprising that I did a video tutorial explaining this concept 2 days ago and you have asked this. Do watch this 9 min video to get a good understanding of this. Here is the explaination. There is a concept called Eventloop in Nodejs and in JS in general. What an Eventloop does is that it keeps a watch on the code that is running and on the stack. As you said what ever is pushed onto the stack from code block is a FIFO. However if there are any async or callback methods or actions that have to be performed then Eventloop jumps into action to take care of these. What eventloop essentially does 8s that it has a queue of its own where it maintains these callback methods. When the stack is free, this piece of code from queue is put onto the stack and is executed.
This is purely because of node js's IO non blocking feature. Your file read operation is an IO thing hence it will be pushed to event queue and the setTimeOut function will be executed immediately. Once the file read is done, using its callback it will join the main control flow. Hence setTimeOut will be executed first and then the File read. Simple.