I am currently trying to test some Node.js code.
Right now I am trying to figure out why my code console.log()'s in different order relative to the code execution order. This is regarding OS related Node.js function calls.
My script does this in order:
//First
fs.readdir(){ //read from a directory all the available files
console.log some stuff #a
}
//Second
fs.readFile(){ //read entire text file
console.log some stuff #b
}
//Third
//create readline interface using fs.createReadStream(filedir) then
interface{ //read from text file line by line
console.log some stuff #c
}
Function a uses the path: __dirname + '/text_file/'
Function b and c uses the path: __dirname, '/text_file/text1.txt'
Output:
a
c
b
Can someone explain why this order happens? I am not an expert in Operating System or what is happening in the background with Node.js. Will this ordering mess up my app if I were to rely on this?
If you start multiple asynchronous operations like this one after the other, the completion order is indeterminate. These operations run independently of your Javascript. They are what is called "non-blocking" which means they return immediately from the function call and your Javascript keeps executing. Some time later, they finish, insert an event in the Javascript event queue and then the callback you passed to them gets called. The "asynchronous, non-blocking" aspect of these functions means that they don't "wait" for the operation to complete before returning.
The order of completion of multiple asynchronous operations that are all in flight at the same time will just depend upon which one finishes it's work before the others.
If you want them to run in sequence, then you have to specifically code them to run sequentially by starting the second operation in the completion callback of the first and starting the third one in the completion callback of the third.
For example:
fs.readdir(somePath, function(err, files) {
if (err) {
console.log(err);
} else {
fs.readFile(someFilename, function(err, data) {
if (err) {
console.log(err);
} else {
// done with both asynchronous operations here
console.log(data);
}
});
}
});
Some other relevant references on the topic:
How to let asynchronous readFile method follow order in node.js
How to synchronize a sequence of promises?
How do I set a specific order of execution when asynchronous calls are involved?
How does Asynchronous Javascript Execution happen? and when not to use return statement?
Single thread synchronous and asynchronous confusion
Why do callbacks functions allow us to do things asynchronously in Javascript?
readdir and readFile are asynchronous, that is, they do processing outside the main flow of code. That is why you get to give them a callback, which is executed once the operation finishes, which might take a long time (in a computer's notion of time).
You cannot rely on asynchronous functions being completed before the next synchronous line of code executes at all. That means, your code will eventually end up looking like this:
fs.readdir(someDir, function(err, files) {
if (err) return;
// do stuff with the list of files in the directory
fs.readFile(someFile, function(err, contents) {
if (err) return;
// do stuff with the file's contents
});
});
Why asynchronous, you might ask? Well, maybe you can go about doing other things while the (very slow) disk spins around trying to find your data. Stopping the whole program while the disk reads would be a very notable waste of time, so Node makes such operations that depend on disk or network asynchronous, which frees you to continue with any other processing until they are done.
Of course, that means you have to write code that depends on the output of such asynchronous operations inside the callback.
In another note:
Hopefully you can see that for big applications, this style of coding is very cumbersome, since the main code would ever go more to the right, and error tracking is tricky. That is why Promises were invented, and I would recommend you learn them, but after you understand normal asynchronicity.
All these functions are asynchronous and will be performed in parallel. fs.readFile will callback will execute after the whole file is read as for fs.createReadStream callback will execute when the first chunk of the stream is readable, and that´s faster than the first one.
Unlike traditional programming languages, JavaScript (and its variants like NodeJS) run the code in parallel, each asynchronous function runs independently from the others and because of this the program wont run in sequence, this makes the execution faster but more difficult to control
to handle synchronous functions there are libraries like ASYNC that will allow you to control what to do when one or more functions end, and will help you limit or eliminate the callback hell
https://www.sohamkamani.com/blog/2016/03/14/wrapping-your-head-around-async-programming/
Related
I know how node.js executes code asynchronously without blocking the main thread of execution by using the event-loop for scheduling the asynchronous tasks, but I'm not clear on how the main thread actually decides to put aside a piece of code for asynchronous execution.
(Basically what indicates that this piece of code should be executed asynchronously and not synchronously, what are the differentiating factors?)
And also, what are the asynchronous and synchronous APIs provided by node?
There is a mistake in your assumption when you ask:
what indicates that this piece of code should be executed asynchronously and not synchronously
The mistake is thinking that some code are executed asynchronously. This is not true.
Javascript (including node.js) executes all code synchronously. There is no part of your code that is executed asynchronously.
So at first glance that is the answer to your question: there is no such thing as asynchronous code execution.
Wait, what?
But what about all the asynchronous stuff?
Like I said, node.js (and javascript in general) executes all code synchronously. However javascript is able to wait for certain events asynchronously. There are no asynchronous code execution, however there is asynchronous waiting.
What's the difference between code execution and waiting?
Let's look an an example. For the sake of clarity I'll use pseudocode in a fake made-up language to remove any confusion from javascript syntax. Let's say we want to read from a file. This fake language supports both synchronous and asynchronous waiting:
Example1. Synchronously wait for the drive to return bytes form the file
data = readSync('filename.txt');
// the line above will pause the execution of code until all the
// bytes have been read
Example2. Asynchronously wait for the drive to return bytes from the file
// Since it is asynchronous we don't want the read function to
// pause the execution of code. Therefore we cannot return the
// data. We need a mechanism to accept the returned value.
// However, unlike javascript, this fake language does not support
// first-class functions. You cannot pass functions as arguments
// to other functions. However, like Java and C++ we can pass
// objects to functions
class MyFileReaderHandler inherits FileReaderHandler {
method callback (data) {
// process file data in here!
}
}
myHandler = new MyFileReaderHandler()
asyncRead('filename.txt', myHandler);
// The function above does not wait for the file read to complete
// but instead returns immediately and allows other code to execute.
// At some point in the future when it finishes reading all data
// it will call the myHandler.callback() function passing it the
// bytes form the file.
As you can see, asynchronous I/O is not special to javascript. It has existed long before javascript in C++ and even C libraries dealing with file I/O, network I/O and GUI programming. In fact it has existed even before C. You can do this kind of logic in assembly (and indeed that's how people design operating systems).
What's special about javascript is that due to it's functional nature (first-class functions) the syntax for passing some code you want to be executed in the future is simpler:
asyncRead('filename.txt', (data) => {
// process data in here
});
or in modern javascript can even be made to look like synchronous code:
async function main () {
data = await asyncReadPromise('filename.txt');
}
main();
What's the difference between waiting and executing code. Don't you need code to check on events?
Actually, you need exactly 0% CPU time to wait for events. You just need to execute some code to register some interrupt handlers and the CPU hardware (not software) will call your interrupt handler when the interrupt occurs. And all manner of hardware are designed to trigger interrupts: keyboards, hard disk, network cards, USB devices, PCI devices etc.
Disk and network I/O are even more efficient because they also use DMA. These are hardware memory readers/writers that can copy large chunks (kilobytes/megabytes) of memory from one place (eg. hard disk) to another place (eg. RAM). The CPU actually only needs to set up the DMA controller and then is free to do something else. Once the DMA controller completes the transfer it will trigger an interrupt which will execute some device driver code which will inform the OS that some I/O event has completed which will inform node.js which will execute your callback or fulfill your Promise.
All the above use dedicated hardware instead of executing instructions on the CPU to transfer data. Thus waiting for data takes 0% CPU time.
So the parallelism in node.js has more to do with how many PCIe lanes your CPU supports than how many CPU cores it has.
You can, if you want to, execute javascript asynchronously
Like any other language, modern javascript has multi-threading support in the form of webworkers in the browser and worker_threads in node.js. But this is regular multi-threading like any other language where you deliberately start another thread to execute your code asynchronously.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
I'm struggling to grasp the concept of asynchronousness. Is the following roughly correct about asynchronous operations?
A problem can occur if a piece of code takes a long time to complete. This is because i) it stops code below from running and it might be nice to run this whilst the hard code loads in the background. And ii) Indeed, JS might try to execute the code below before the hard code’s finished. If the code below relies on the hard code, that’s a problem.
A solution is: if an operation takes a long time to complete, you want to process it in a separate thread while the original thread is processed. Just make sure the main thread doesn't reference things that the asynchronous operation returns. JS employs event-ques for this solution. Asynchronous operations are executed in an event-que which executes after the main-thread.
But even the event-que can suffer from the same problem as the main-thread. If fetch1, which is positioned above fetch2, takes a long time to return a promise, and fetch2 doesn’t, JS might start executing fetch2 before executing fetch1. This is where Promise.all is useful because it won't proceed with the next step in the asynchronous operation until both both fetch1 & fetch2’s promises are resolved.
On a separate note, I’ve read when chaining .then, that counts as one asynchronous operation so we can always guarantee that the subsequent .thenwill only execute when the .then before it has executed|resolved its promise.
Almost correct but not quite.
If you are talking about "asynchronousness" the word in the English language then it just means that things can happen out of order. This concept is used in a lot of languages including multithreading in Java and C/C++.
If you are talking about the specific concept of asynchronousness as it relates to node.js or asynchronous I/O in C/C++ then you do have some misunderstandings in how this works at the low level.
A problem can occur if a piece of code takes a long time to complete. This is because i) it stops code below from running and it might be nice to run this whilst the hard code loads in the background. And ii) Indeed, JS might try to execute the code below before the hard code’s finished. If the code below relies on the hard code, that’s a problem.
When talking about javascript or asynchronous I/O in C/C++ (where javascript got its asynchronousness from) this is not true.
What actually happens is that waiting for something to happen may take a long time to complete. Instead of waiting why not tell the OS to execute some code (your callback) once that thing happens.
At the OS level most modern operating systems have API that let you tell it to wake your process up when something happens. That thing may be a keyboard event, a mouse event, an I/O event (from disk or network), a system reconfiguration event (eg. changing monitor resolution) etc.
Most traditional languages implement blocking I/O. What happens is that when you try to read something form disk or network your process goes to sleep immediately and the OS will wake it up again when the data arrives:
Traditional blocking I/O
time
│
├────── your code doing stuff ..
├────── read_data_from_disk() ───────────────────┐
┆ ▼
: OS puts process to sleep
.
. other programs running ..
.
: data arrives ..
┆ OS wakes up your process
├────── read_data_from_disk() ◀──────────────────┘
├────── your program resume doing stuff ..
▼
This means that your program can only wait for one thing at a time. Which means that most of the time your program is not using the CPU. The traditional solution to listen to more events is multithreading. Each thread will seperately block on their events but your program can spawn a new thread for each event it is interested in.
It turns out that naive multithreading where each thread waits for one event is slow. Also it ends up consuming a lot of RAM especially for scripting languages. So this is not what javascript does.
Note: Historically the fact that javascript uses a single thread instead of multithreading is a bit of an accident. It was just the result of decisions made by the team that added progressive JPEG rendering and GIF animations to early browsers. But by happy coincidence this is exactly what makes things like node.js fast.
What javascript does instead is wait for multiple events instead of waiting for a single event. All modern OSes have API that lets you wait for multiple events. They range from queue/kqueue on BSD and Mac OSX to poll/epoll on Linux to overlapped I/O on Windows to the cross-platform POSIX select() system call.
The way javascript handles external events is something like the following:
Non-blocking I/O (also known as asynchronous I/O)
time
│
├────── your code doing stuff ..
├────── read_data_from_disk(read_callback) ───▶ javascript stores
│ your callback and
├────── your code doing other stuff .. remember your request
│
├────── wait_for_mouse_click(click_callback) ─▶ javascript stores
│ your callback and
├────── your code doing other stuff .. remember your request
│
├────── your finish doing stuff.
┆ end of script ─────────────▶ javascript now is free to process
┆ pending requests (this is called
┆ "entering the event loop").
┆ Javascript tells the OS about all the
: events it is interested in and waits..
. │
. └───┐
. ▼
. OS puts process to sleep
.
. other programs running ..
.
. data arrives ..
. OS wakes up your process
. │
. ┌───┘
: ▼
┆ Javascript checks which callback it needs to call
┆ to handle the event. It calls your callback.
├────── read_callback() ◀────────────────────┘
├────── your program resume executing read_callback
▼
The main difference is that synchronous multithreaded code waits for one event per thread. Asynchronous code either single threaded like javascript or multi threaded like Nginx or Apache wait for multiple events per thread.
Note: Node.js handles disk I/O in separate threads but all network I/O are processed in the main thread. This is mainly because asynchronous disk I/O APIs are incompatible across Windows and Linux/Unix. However it is possible to do disk I/O in the main thread. The Tcl language is one example that does asynchronous disk I/O in the main thread.
A solution is: if an operation takes a long time to complete, you want to process it in a separate thread while the original thread is processed.
This is not what happens with asynchronous operations in javascript with the exception of web workers (or worker threads in Node.js). In the case of web workers then yes, you are executing code in a different thread.
But even the event-que can suffer from the same problem as the main-thread. If fetch1, which is positioned above fetch2, takes a long time to return a promise, and fetch2 doesn’t, JS might start executing fetch2 before executing fetch1
This is not what is happening. What you are doing is as follows:
fetch(url_1).then(fetch1); // tell js to call fetch1 when this completes
fetch(url_2).then(fetch2); // tell js to call fetch2 when this completes
It is not that js "might" start executing. What happens with the code above is both fetches are executed synchronously. That is, the first fetch strictly happens before the second fetch.
However, all the above code does is tell javascript to call the functions fetch1 and fetch2 back at some later time. This is an important lesson to remember. The code above does not execute the fetch1 and fetch2 functions (the callbacks). All you are doing is tell javascript to call them when the data arrives.
If you do the following:
fetch(url_1).then(fetch1); // tell js to call fetch1 when this completes
fetch(url_2).then(fetch2); // tell js to call fetch2 when this completes
while (1) {
console.log('wait');
}
Then the fetch1 and fetch2 will never get executed.
I'll pause here to let you ponder on that.
Remember how asynchronous I/O is handled. All I/O (often called asynchronous) function calls don't actually cause the I/O to be accessed immediately. All they do is just remind javascript that you want something (a mouse click, a network request, a timeout etc.) and you want javascript to execute your function later when that thing completes. Asynchronous I/O are only processed at the end of your script when there is no more code to execute.
This does mean that you cannot use an infinite while loop in a javascript program. Not because javascript does not support it but there is a built-in while loop that surrounds your entire program: this big while loop is called the event loop.
On a separate note, I’ve read when chaining .then, that counts as one asynchronous operation.
Yes, this is by design to avoid confusing people on when promises are processed.
If you are interested at how the OS handles all this without further creating threads you may be interested in my answers to these related questions:
Is there any other way to implement a "listening" function without an infinite while loop?
node js - what happens to incoming events during callback excution
TLDR
If nothing else I'd like you to understand two things:
Javascript is a strictly synchronous programming language. Each statement in your code is executed strictly sequentially.
Asynchronous code in all languages (yes, including C/C++ and Java and Python etc.) will call your callback at any later time. Your callback will not be called immediately. Asynchronousness is a function-call level concept.
It's not that javascript is anything special when it comes to asynchronousness*. It's just that most javascript libraries are asynchronous by default (though you can also write asynchronous code in any other language but their libraries are normally synchronous by default).
*Note: of course, things like async/await does make javascript more capable of handling asynchronous code.
Side note: Promises are nothing special. It is just a design pattern. It is not something built-in to javascript syntax. It is just that newer versions of javascript comes with Promises as part of its standard library. You could have always used promises even with very old versions of javascript and in other languages (Java8 and above for example call have promises in their standard library but call them Futures).
This page explains Node.js event loop very well (since it's by Node.js):
https://nodejs.dev/learn/the-nodejs-event-loop
A problem can occur if a piece of code takes a long time to complete.
This is because i) it stops code below from running and it might be
nice to run this whilst the hard code loads in the background. And ii)
Indeed, JS might try to execute the code below before the hard code’s
finished. If the code below relies on the hard code, that’s a problem.
Yes, though to reword: having a user wait for code to resolve is bad user experience rather than a runtime error. Still, a runtime error would indeed occur if a code block was dependent on a variable that returned undefined because it had yet to resolve.
A solution is: if an operation takes a long time to complete, you want
to process it in a separate thread while the original thread is
processed. Just make sure the main thread doesn't reference things
that the asynchronous operation returns. JS employs event-ques for
this solution. Asynchronous operations are executed in an event-que
which executes after the main-thread.
Yes, but it is important to point out these other threads are occurring in the browser or on an api server, not within your JS script. Also, async functions are still called in the main call stack, but their resolve is placed in either the job queue or message queue.
But even the event-que can suffer from the same problem as the
main-thread. If fetch1, which is positioned above fetch2, takes a long
time to return a promise, and fetch2 doesn’t, JS might start executing
fetch2 before executing fetch1. This is where Promise.all is useful
because it won't proceed with the next step in the asynchronous
operation until both both fetch1 & fetch2’s promises are resolved.
Yes, a promise's resolve is executed as soon as the current function in the call stack resolves. If one promise resolves before another, its resolve will executed first event if it was called second. Also note that Promise.all doesn't change the resolve time, but rather returns the resolves together in the order their promise was executed.
On a separate note, I’ve read when chaining .then, that counts as one
asynchronous operation so we can always guarantee that the subsequent
.thenwill only execute when the .then before it has executed|resolved
its promise.
Yes, though the newer and cleaner syntax is async await:
function A () {
return new Promise((resolve, reject)=> setTimeout(()=> resolve("done"),2000))
}
async function B () {
try {
console.log("waiting...");
const result = await A();
console.log(result);
} catch (e) {
console.log(e);
}
}
B();
And below shows the Node.js callstack in action:
function A () {
return new Promise((resolve, reject)=> resolve(console.log("A")))
}
function B () {
console.log("B");
C();
}
function C () {
console.log("C");
}
function D () {
setTimeout(()=> console.log("D"),0);
}
B();
D();
A();
B gets called, C gets called, B resolves, D gets called, setTimeout gets called but its resolve is moved to the message queue, D resolves, A gets called, the promise gets called and immediately resolves, A resolves, the call stack completes, the message queue is accessed
I'm writing a node backend and I'm a little confused how should I deal with async functions. I've read about process.nextTick(), but how often should I use. Most of my code is based on callbacks, like database calls, which are asynchronous by themselves. But I also have a few functions of my own, that should be async.
So which one is a good example of async function?
function validateUser1(user, callback) {
process.nextTick(function() {
//validate user, some regex and stuff
callback(err, user);
});
}
function validateUser2(user, callback) {
//validate user, some regex and stuff
process.nextTick(callback, err, user);
}
function validateUser3(user, callback) {
process.nextTick(function() {
//validate user, some regex and stuff
process.nextTick(callback, err, user);
});
}
I don't know whether I should wrap everything in process.nextTick , or wrap just the callback? or both?
And overall, the idea with node.js is to write lots of small functions rather than bigger ones, and call them asynchronously to not block other events, right?
If you have just CPU code (no I/O) you should try and go as far along as you can. Avoid async and tiny functions which fragment your code unnecessarily.
Take the opportunity and write clean, readable, linear code whenever possible. Only revert to async when absolutely necessary, such as stream I/O (file or network).
Consider this. Even if you have 1000+ lines of JS code, it will still be executed blazingly fast. You really do not need to fragment it (unless proven to be too cumbersome, such as very deep loops, but you have to measure it first)!
If you don't test the linear code first and actually SEE that you need to fragment it, you'll end up with premature optimization, which is a bad thing for maintainability.
I'd really go straight away with this:
function validateUser1(user, callback) {
//validate user, some regex and stuff
callback(err, user);
}
And if possible, remove the function altogether (but this is a matter of how you write the rest of the code).
Also, don't use nextTick() if you don't really need it. I've implemented a cloud server with many TCP/IP sockets, database connections, logging, file reading and a lot of I/O, but NOT ONCE did I use nextTick() and it runs really smooth.
process.nextTick() will execute your callback before continuing with the event loop. This will block your thread and can stop incoming connections from being handled if the callback you passed to process.nextTick() is something CPU expensive like encrypting, calculating PI etc.
From what I understand you try to make your functions asynchronous by passing them to process.nextTick(). That is not how it works.
When you pass something to process.nextTick() it will execute before the eventloop is executed the next time. This will not make your function non-blocking, as the function you execute is still running in the main thread. Only I/O Operations can be non-blocking.
Therefore it is irrelevant if you wrap your CPU-intensive functions with process.nextTick() or just execute them right away.
If you want to read more background information, here is the resource: https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/#process-nexttick
I still confused with the answer provided.
I watched short course on Lynda.com about NodeJS (Advanced NodeJS).
The guy provides the following example of using process.nextTick()
function hideString(str, done) {
process.nextTick(()=> {
done(str.replace(/[a-zA-Z]/g, 'X'))
})
}
hideString("Hello World", (hidden) => {
console.log( hidden );
});
console.log('end')
If you do not use, console.log('end') will be printed first. not async.
I understood it as to write async code, you will need process.nextTick.
Than it is not clear how async code is written in JS on frontend without process.next Tick()
Recently, I have been developing web application and I realize that I am not making use of the asynchronous property at all. Hence I am ending up with a lot of nested callbacks.
For example, if the user want to get a file from the server through a particular API, I will have code similar to this,
db.query(<select list of permitted files_names>, function(err, filenames) {
async.each(file_names, function(name, next) {
//open each file to put into array
});
})
This code needs to query database to get a list of file names before looping asynchronously and putting each file content into an array. Finally it will return the finished array to the client.
With the nested callback, and async library, this code is behaving like a synchronous code.
names = db.querySync(//select list of permitted files_names);
for(name in names) {
//open each file to put into array
}
I am better off writing synchronous code like this since it is much neater. My use case might be a little strange but most of my api behaves in similar manner and that makes me think why do I even need asynchronous function?
Can someone please enlighten me if there are any differences between these two codes in term of performance? How do I make use of non-blocking property to enhance the performance in this use case?
If you're writing callback functions you're using by definition using async calls. The callback function fires only when the operation is complete or has errored out. You don't need a fancy library to use these, this is the backbone of how Node's event-loop driven subsystem operates.
Node strongly advises against using "Sync" calls. The Node core only includes a handful as a convenience, they're there as last-resort tools. Many libraries don't even support them so you absolutely must get used to writing async code. In the browser environment, for example, you simply cannot use blocking calls without jamming up the JavaScript runtime and stalling the page.
I prefer using Promises line Bluebird implements to keep code orderly. There are other ways, like the async library, which can help manage otherwise complicated nesting patterns.
Some of the perks include things like Promise.all method runs a series of promises to completion and then triggers a next step, and Promise.map which iterates over a list, running async code for each element, then advancing when the list is complete.
If you're disciplined about organizing your code it's not too bad. Node does require a lot more attention being paid to the order of operations than in a traditional sync-by-default language like Ruby, Python or Java, but you can get used to it. Once you start working with async code rather than fighting it you can often do a ton of work quickly, efficiently, and with a minimum of fuss, in many cases more effectively than in other languages where you must juggle threads plus locking and/or deal with IPC.
Yes, there is a difference in the two codes in terms of performance.
In synchronous code:
names = db.querySync(//select list of permitted files_names);
you are calling the database here to give list of names. Assume , this takes 10 sec. So for this time, nodeJS as it is single threaded gos into blocking state. After 10 sec, it executes the rest of the code . Assume this for loop takes 5 sec and some code takes 5 sec.
for(name in names) {
//open each file to put into array
}
//some code
Therefore it takes a total time of 20 sec.
whereas in Asynchronous code:
db.query(<select list of permitted files_names>, function(err, filenames) {
NodeJs will ask the database to give list of names to a callback. Assume that it takes 10 sec. And immediately it goes into the next step(some code), but not into the blocking state. Assume that some code takes 5 sec.
async.each(file_names, function(name, next) {
//open each file to put into array
});
})
//some code.
After 5 sec, it will check whether it has an i/o operations to be performed. Once the call back is returned. It will execute the function(name, next) {..} for the 5 sec.
So the total time here is 15sec.
In this manner the performance is improved.
If the asynchronous code should be clear and neat then make use of closures & promises.
For ex: Above asynchronous code can be written as
fun = function(err, filenames) {
async.each(file_names, function(name, next) {
//open each file to put into array
}
db.query(<select list of permitted files_names>, fun);
The benefit is simple: By using asynchronous code, the current thread (remember, Node.js is single-threaded) is able to handle other requests while the current request is waiting on something (like a database query) to return.
If you use synchronous code instead, the current thread will block while it waits, and it won't be able to handle other requests in the meantime. In other words, you lose concurrency.
To keep your asynchronous code clean, look into promises (to avoid deeply nested callbacks) and ES7 async/await (to avoid callbacks at all and write asynchronous code that looks just like synchronous code).
I saw this post: https://www.codementor.io/nodejs/tutorial/manage-async-nodejs-callback-example-code, and after running the codes I confirm that nodejs is asynchronus.
However I created 2 js files to test asynchronus feature of nodejs again.
File 1: callback_example.js
exports.countless = function(callback){
var date = new Date();
console.log("*" + date.getSeconds());
var x = 0;
for(var i = 1; i <= 1000000000; i++){
x++;
}
callback(x);
date = new Date();
console.log("**" + date.getSeconds());
}
exports.check = function(callback){
var date = new Date();
console.log(date.getSeconds());
callback(123);
date = new Date();
console.log(date.getSeconds());
}
File 2: call.js
var call = require('./callback_example');
call.countless(function(x){
console.log(x);
});
call.check(function(x){
console.log(x);
});
And when I execute call.js in terminal as node call, I saw that after countless() finished, then check() run. It means that nodejs is synchronus? Why? Can anyone help me answer that? Thank you very much!
when u r calling call.countless() it is executing that function however there is nothing blocking I/O inside that. So Runtime is busy with doing for loop operation. If u had written any Blocking I/O operation then you would have seen the asynchronous nature of NODE JS.
e.g., Blocking I/O Operation: File Read/Write, TimeOut, DB Operation, Ajax call
After the for loop is complete then Interpreter goes to second function.
node.js uses the V8 Javascript engine and it executes lines of Javascript synchronous one after the other. If you write sequential coding statements such as in both your countless and check methods in your question, then those are executed synchronously just like in pretty much any other programming language.
Here's part of the node.js description from https://nodejs.org/en/.
Node.js uses an event-driven, non-blocking I/O model that makes it
lightweight and efficient.
This, I think, describes it better than just saying node.js is asynchronous as it described better what it actually does.
Only real asynchronous operations that make use of some outside interface such as networking are actually non-blocking in node.js. In that case, calling the non-blocking function starts the operation and then Javascript execution continues on the next lines of Javascript. When the non-blocking operation completes some time in the future, an event is inserted in the event queue and when the V8 engine has finished executing the current thread of execution, that event can be pulled from the event queue and a callback will get called.
You cannot write truly asynchronous operations from scratch (where actual code gets executed in the background) in pure Javascript. You need help from an external interface (such as networking, file I/O, etc...) in order create an actual async operation. You can simulate one with timers, but that isn't actually asynchronous because nothing actually executes in the background. Timers just shift the timing of when things run (they don't actually do work in parallel with your Javascript execution).
Here's an example of an asynchronous operation in node.js:
var fs = require('fs');
console.log("one");
fs.readFile('temp.txt', function(err, data) {
if (err) {
console.log(err);
} else {
console.log("got data");
}
});
console.log("two");
This will generate the following output:
one
two
got data
The fs.readFile() operation is actually asynchronous. After you call it, it does its work in the background while the rest of your Javascript in the statements that follow continue to execute. When it completes, sometime in the future, it will call it's callback with either an error or the data.
Node in itself is not asynchronous, it just uses an event loop as a primary construct. Iterations of the event loop are executed synchronously, just like any other programming language.
Your example here does not use asynchronous code at all. Just because something is inside of a callback doesn't necessarily mean it is asynchronous (otherwise map would be asynchronous, for example). You're simply employing higher-order functions here.
Try putting these both inside individual setTimeouts; the invocation order will not be guaranteed.
Node guarantees run-to-completion (that is, any function will be wholly executed unless it throws until the first return statement), so any synchronous code will be executed in the order it is written - just like any other imperative language. Any I/O operations or things like using a Promise will however have their callbacks added to a task queue to be executed at some point in the future, so their execution order is not guaranteed.
Note that NodeJS is single-threaded and large for loops will eat up that single thread as it is a CPU bound operation, so take care when doing computationally heavy stuff like that as you will hang your entire application. For computationally heavy stuff you could yield to using a child process written in another language better suited for such a thing (using the child_process module).