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
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.
I thought that they were basically the same thing — writing programs that split tasks between processors (on machines that have 2+ processors). Then I'm reading this, which says:
Async methods are intended to be non-blocking operations. An await
expression in an async method doesn’t block the current thread while
the awaited task is running. Instead, the expression signs up the rest
of the method as a continuation and returns control to the caller of
the async method.
The async and await keywords don't cause additional threads to be
created. Async methods don't require multithreading because an async
method doesn't run on its own thread. The method runs on the current
synchronization context and uses time on the thread only when the
method is active. You can use Task.Run to move CPU-bound work to a
background thread, but a background thread doesn't help with a process
that's just waiting for results to become available.
and I'm wondering whether someone can translate that to English for me. It seems to draw a distinction between asynchronicity (is that a word?) and threading and imply that you can have a program that has asynchronous tasks but no multithreading.
Now I understand the idea of asynchronous tasks such as the example on pg. 467 of Jon Skeet's C# In Depth, Third Edition
async void DisplayWebsiteLength ( object sender, EventArgs e )
{
label.Text = "Fetching ...";
using ( HttpClient client = new HttpClient() )
{
Task<string> task = client.GetStringAsync("http://csharpindepth.com");
string text = await task;
label.Text = text.Length.ToString();
}
}
The async keyword means "This function, whenever it is called, will not be called in a context in which its completion is required for everything after its call to be called."
In other words, writing it in the middle of some task
int x = 5;
DisplayWebsiteLength();
double y = Math.Pow((double)x,2000.0);
, since DisplayWebsiteLength() has nothing to do with x or y, will cause DisplayWebsiteLength() to be executed "in the background", like
processor 1 | processor 2
-------------------------------------------------------------------
int x = 5; | DisplayWebsiteLength()
double y = Math.Pow((double)x,2000.0); |
Obviously that's a stupid example, but am I correct or am I totally confused or what?
(Also, I'm confused about why sender and e aren't ever used in the body of the above function.)
Your misunderstanding is extremely common. Many people are taught that multithreading and asynchrony are the same thing, but they are not.
An analogy usually helps. You are cooking in a restaurant. An order comes in for eggs and toast.
Synchronous: you cook the eggs, then you cook the toast.
Asynchronous, single threaded: you start the eggs cooking and set a timer. You start the toast cooking, and set a timer. While they are both cooking, you clean the kitchen. When the timers go off you take the eggs off the heat and the toast out of the toaster and serve them.
Asynchronous, multithreaded: you hire two more cooks, one to cook eggs and one to cook toast. Now you have the problem of coordinating the cooks so that they do not conflict with each other in the kitchen when sharing resources. And you have to pay them.
Now does it make sense that multithreading is only one kind of asynchrony? Threading is about workers; asynchrony is about tasks. In multithreaded workflows you assign tasks to workers. In asynchronous single-threaded workflows you have a graph of tasks where some tasks depend on the results of others; as each task completes it invokes the code that schedules the next task that can run, given the results of the just-completed task. But you (hopefully) only need one worker to perform all the tasks, not one worker per task.
It will help to realize that many tasks are not processor-bound. For processor-bound tasks it makes sense to hire as many workers (threads) as there are processors, assign one task to each worker, assign one processor to each worker, and have each processor do the job of nothing else but computing the result as quickly as possible. But for tasks that are not waiting on a processor, you don't need to assign a worker at all. You just wait for the message to arrive that the result is available and do something else while you're waiting. When that message arrives then you can schedule the continuation of the completed task as the next thing on your to-do list to check off.
So let's look at Jon's example in more detail. What happens?
Someone invokes DisplayWebSiteLength. Who? We don't care.
It sets a label, creates a client, and asks the client to fetch something. The client returns an object representing the task of fetching something. That task is in progress.
Is it in progress on another thread? Probably not. Read Stephen's article on why there is no thread.
Now we await the task. What happens? We check to see if the task has completed between the time we created it and we awaited it. If yes, then we fetch the result and keep running. Let's suppose it has not completed. We sign up the remainder of this method as the continuation of that task and return.
Now control has returned to the caller. What does it do? Whatever it wants.
Now suppose the task completes. How did it do that? Maybe it was running on another thread, or maybe the caller that we just returned to allowed it to run to completion on the current thread. Regardless, we now have a completed task.
The completed task asks the correct thread -- again, likely the only thread -- to run the continuation of the task.
Control passes immediately back into the method we just left at the point of the await. Now there is a result available so we can assign text and run the rest of the method.
It's just like in my analogy. Someone asks you for a document. You send away in the mail for the document, and keep on doing other work. When it arrives in the mail you are signalled, and when you feel like it, you do the rest of the workflow -- open the envelope, pay the delivery fees, whatever. You don't need to hire another worker to do all that for you.
In-browser Javascript is a great example of an asynchronous program that has no multithreading.
You don't have to worry about multiple pieces of code touching the same objects at the same time: each function will finish running before any other javascript is allowed to run on the page. (Update: Since this was written, JavaScript has added async functions and generator functions. These functions do not always run to completion before any other javascript is executed: whenever they reach a yield or await keyword, they yield execution to other javascript, and can continue execution later, similar to C#'s async methods.)
However, when doing something like an AJAX request, no code is running at all, so other javascript can respond to things like click events until that request comes back and invokes the callback associated with it. If one of these other event handlers is still running when the AJAX request gets back, its handler won't be called until they're done. There's only one JavaScript "thread" running, even though it's possible for you to effectively pause the thing you were doing until you have the information you need.
In C# applications, the same thing happens any time you're dealing with UI elements--you're only allowed to interact with UI elements when you're on the UI thread. If the user clicked a button, and you wanted to respond by reading a large file from the disk, an inexperienced programmer might make the mistake of reading the file within the click event handler itself, which would cause the application to "freeze" until the file finished loading because it's not allowed to respond to any more clicking, hovering, or any other UI-related events until that thread is freed.
One option programmers might use to avoid this problem is to create a new thread to load the file, and then tell that thread's code that when the file is loaded it needs to run the remaining code on the UI thread again so it can update UI elements based on what it found in the file. Until recently, this approach was very popular because it was what the C# libraries and language made easy, but it's fundamentally more complicated than it has to be.
If you think about what the CPU is doing when it reads a file at the level of the hardware and Operating System, it's basically issuing an instruction to read pieces of data from the disk into memory, and to hit the operating system with an "interrupt" when the read is complete. In other words, reading from disk (or any I/O really) is an inherently asynchronous operation. The concept of a thread waiting for that I/O to complete is an abstraction that the library developers created to make it easier to program against. It's not necessary.
Now, most I/O operations in .NET have a corresponding ...Async() method you can invoke, which returns a Task almost immediately. You can add callbacks to this Task to specify code that you want to have run when the asynchronous operation completes. You can also specify which thread you want that code to run on, and you can provide a token which the asynchronous operation can check from time to time to see if you decided to cancel the asynchronous task, giving it the opportunity to stop its work quickly and gracefully.
Until the async/await keywords were added, C# was much more obvious about how callback code gets invoked, because those callbacks were in the form of delegates that you associated with the task. In order to still give you the benefit of using the ...Async() operation, while avoiding complexity in code, async/await abstracts away the creation of those delegates. But they're still there in the compiled code.
So you can have your UI event handler await an I/O operation, freeing up the UI thread to do other things, and more-or-less automatically returning to the UI thread once you've finished reading the file--without ever having to create a new thread.
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.
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).
I have been under the impression for that JavaScript was always asynchronous. However, I have learned that there are situations where it is not (ie DOM manipulations). Is there a good reference anywhere about when it will be synchronous and when it will be asynchronous? Does jQuery affect this at all?
JavaScript is always synchronous and single-threaded. If you're executing a JavaScript block of code on a page then no other JavaScript on that page will currently be executed.
JavaScript is only asynchronous in the sense that it can make, for example, Ajax calls. The Ajax call will stop executing and other code will be able to execute until the call returns (successfully or otherwise), at which point the callback will run synchronously. No other code will be running at this point. It won't interrupt any other code that's currently running.
JavaScript timers operate with this same kind of callback.
Describing JavaScript as asynchronous is perhaps misleading. It's more accurate to say that JavaScript is synchronous and single-threaded with various callback mechanisms.
jQuery has an option on Ajax calls to make them synchronously (with the async: false option). Beginners might be tempted to use this incorrectly because it allows a more traditional programming model that one might be more used to. The reason it's problematic is that this option will block all JavaScript on the page until it finishes, including all event handlers and timers.
JavaScript is single threaded and has a synchronous execution model. Single threaded means that one command is being executed at a time. Synchronous means one at a time i.e. one line of code is being executed at time in order the code appears. So in JavaScript one thing is happening at a time.
Execution Context
The JavaScript engine interacts with other engines in the browser.
In the JavaScript execution stack there is global context at the bottom and then when we invoke functions the JavaScript engine creates new execution contexts for respective functions. When the called function exits its execution context is popped from the stack, and then next execution context is popped and so on...
For example
function abc()
{
console.log('abc');
}
function xyz()
{
abc()
console.log('xyz');
}
var one = 1;
xyz();
In the above code a global execution context will be created and in this context var one will be stored and its value will be 1... when the xyz() invocation is called then a new execution context will be created and if we had defined any variable in xyz function those variables would be stored in the execution context of xyz(). In the xyz function we invoke abc() and then the abc() execution context is created and put on the execution stack... Now when abc() finishes its context is popped from stack, then the xyz() context is popped from stack and then global context will be popped...
Now about asynchronous callbacks; asynchronous means more than one at a time.
Just like the execution stack there is the Event Queue. When we want to be notified about some event in the JavaScript engine we can listen to that event, and that event is placed on the queue. For example an Ajax request event, or HTTP request event.
Whenever the execution stack is empty, like shown in above code example, the JavaScript engine periodically looks at the event queue and sees if there is any event to be notified about. For example in the queue there were two events, an ajax request and a HTTP request. It also looks to see if there is a function which needs to be run on that event trigger... So the JavaScript engine is notified about the event and knows the respective function to execute on that event... So the JavaScript engine invokes the handler function, in the example case, e.g. AjaxHandler() will be invoked and like always when a function is invoked its execution context is placed on the execution context and now the function execution finishes and the event ajax request is also removed from the event queue... When AjaxHandler() finishes the execution stack is empty so the engine again looks at the event queue and runs the event handler function of HTTP request which was next in queue. It is important to remember that the event queue is processed only when execution stack is empty.
For example see the code below explaining the execution stack and event queue handling by Javascript engine.
function waitfunction() {
var a = 5000 + new Date().getTime();
while (new Date() < a){}
console.log('waitfunction() context will be popped after this line');
}
function clickHandler() {
console.log('click event handler...');
}
document.addEventListener('click', clickHandler);
waitfunction(); //a new context for this function is created and placed on the execution stack
console.log('global context will be popped after this line');
And
<html>
<head>
</head>
<body>
<script src="program.js"></script>
</body>
</html>
Now run the webpage and click on the page, and see the output on console. The output will be
waitfunction() context will be popped after this line
global context will be emptied after this line
click event handler...
The JavaScript engine is running the code synchronously as explained in the execution context portion, the browser is asynchronously putting things in event queue. So the functions which take a very long time to complete can interrupt event handling. Things happening in a browser like events are handled this way by JavaScript, if there is a listener supposed to run, the engine will run it when the execution stack is empty. And events are processed in the order they happen, so the asynchronous part is about what is happening outside the engine i.e. what should the engine do when those outside events happen.
So JavaScript is always synchronous.
JavaScript is single-threaded, and all the time you work on a normal synchronous code-flow execution.
Good examples of the asynchronous behavior that JavaScript can have are events (user interaction, Ajax request results, etc) and timers, basically actions that might happen at any time.
I would recommend you to give a look to the following article:
How JavaScript Timers Work
That article will help you to understand the single-threaded nature of JavaScript and how timers work internally and how asynchronous JavaScript execution works.
To someone who really understands how JS works this question might seem off, however most people who use JS do not have such a deep level of insight (and don't necessarily need it) and to them this is a fairly confusing point, I will try to answer from that perspective.
JS is synchronous in the way its code is executed. each line only runs after the line before it has completed and if that line calls a function after that is complete etc...
The main point of confusion arises from the fact that your browser is able to tell JS to execute more code at anytime (similar to how you can execute more JS code on a page from the console). As an example JS has Callback functions who's purpose is to allow JS to BEHAVE asynchronously so further parts of JS can run while waiting for a JS function that has been executed (I.E. a GET call) to return back an answer, JS will continue to run until the browser has an answer at that point the event loop (browser) will execute the JS code that calls the callback function.
Since the event loop (browser) can input more JS to be executed at any point in that sense JS is asynchronous (the primary things that will cause a browser to input JS code are timeouts, callbacks and events)
I hope this is clear enough to be helpful to somebody.
Definition
The term "asynchronous" can be used in slightly different meanings, resulting in seemingly conflicting answers here, while they are actually not. Wikipedia on Asynchrony has this definition:
Asynchrony, in computer programming, refers to the occurrence of events independent of the main program flow and ways to deal with such events. These may be "outside" events such as the arrival of signals, or actions instigated by a program that take place concurrently with program execution, without the program blocking to wait for results.
non-JavaScript code can queue such "outside" events to some of JavaScript's event queues. But that is as far as it goes.
No Preemption
There is no external interruption of running JavaScript code in order to execute some other JavaScript code in your script. Pieces of JavaScript are executed one after the other, and the order is determined by the order of events in each event queue, and the priority of those queues.
For instance, you can be absolutely sure that no other JavaScript (in the same script) will ever execute while the following piece of code is executing:
let a = [1, 4, 15, 7, 2];
let sum = 0;
for (let i = 0; i < a.length; i++) {
sum += a[i];
}
In other words, there is no preemption in JavaScript. Whatever may be in the event queues, the processing of those events will have to wait until such piece of code has ran to completion. The EcmaScript specification says in section 8.4 Jobs and Jobs Queues:
Execution of a Job can be initiated only when there is no running execution context and the execution context stack is empty.
Examples of Asynchrony
As others have already written, there are several situations where asynchrony comes into play in JavaScript, and it always involves an event queue, which can only result in JavaScript execution when there is no other JavaScript code executing:
setTimeout(): the agent (e.g. browser) will put an event in an event queue when the timeout has expired. The monitoring of the time and the placing of the event in the queue happens by non-JavaScript code, and so you could imagine this happens in parallel with the potential execution of some JavaScript code. But the callback provided to setTimeout can only execute when the currently executing JavaScript code has ran to completion and the appropriate event queue is being read.
fetch(): the agent will use OS functions to perform an HTTP request and monitor for any incoming response. Again, this non-JavaScript task may run in parallel with some JavaScript code that is still executing. But the promise resolution procedure, that will resolve the promise returned by fetch(), can only execute when the currently executing JavaScript has ran to completion.
requestAnimationFrame(): the browser's rendering engine (non-JavaScript) will place an event in the JavaScript queue when it is ready to perform a paint operation. When JavaScript event is processed the callback function is executed.
queueMicrotask(): immediately places an event in the microtask queue. The callback will be executed when the call stack is empty and that event is consumed.
There are many more examples, but all these functions are provided by the host environment, not by core EcmaScript. With core EcmaScript you can synchronously place an event in a Promise Job Queue with Promise.resolve().
Language Constructs
EcmaScript provides several language constructs to support the asynchrony pattern, such as yield, async, await. But let there be no mistake: no JavaScript code will be interrupted by an external event. The "interruption" that yield and await seem to provide is just a controlled, predefined way of returning from a function call and restoring its execution context later on, either by JS code (in the case of yield), or the event queue (in the case of await).
DOM event handling
When JavaScript code accesses the DOM API, this may in some cases make the DOM API trigger one or more synchronous notifications. And if your code has an event handler listening to that, it will be called.
This may come across as pre-emptive concurrency, but it is not: it is the JavaScript code that initiates the API call, and thus controls that the API can do some stuff, but this is just like a function call: once your event handler(s) return(s), the DOM API will eventually also return, and the original JavaScript code will continue after the API call it made.
In other cases the DOM API will just dispatch an event in the appropriate event queue, and JavaScript will pick it up once the call stack has been emptied.
See synchronous and asynchronous events
"I have been under the impression for that JavaScript was always
asynchronous"
You can use JavaScript in a synchronous way, or an asynchronous way. In fact JavaScript has really good asynchronous support. For example I might have code that requires a database request. I can then run other code, not dependent on that request, while I wait for that request to complete. This asynchronous coding is supported with promises, async/await, etc. But if you don't need a nice way to handle long waits then just use JS synchronously.
What do we mean by 'asynchronous'. Well it does not mean multi-threaded, but rather describes a non-dependent relationship. Check out this image from this popular answer:
A-Start ------------------------------------------ A-End
| B-Start -----------------------------------------|--- B-End
| | C-Start ------------------- C-End | |
| | | | | |
V V V V V V
1 thread->|<-A-|<--B---|<-C-|-A-|-C-|--A--|-B-|--C-->|---A---->|--B-->|
We see that a single threaded application can have async behavior. The work in function A is not dependent on function B completing, and so while function A began before function B, function A is able to complete at a later time and on the same thread.
So, just because JavaScript executes one command at a time, on a single thread, it does not then follow that JavaScript can only be used as a synchronous language.
"Is there a good reference anywhere about when it will be synchronous and when it will be asynchronous"
I'm wondering if this is the heart of your question. I take it that you mean how do you know if some code you are calling is async or sync. That is, will the rest of your code run off and do something while you wait for some result? Your first check should be the documentation for whichever library you are using. Node methods, for example, have clear names like readFileSync. If the documentation is no good there is a lot of help here on SO. EG:
How to know if a function is async?