I’ve been reading about callback functions here, and learned that JavaScript is a single-thread synchronous language.
This means that if you want to collect data from a database then you’d have to wait for the routine to finish before any more code was executed. Is this true? What would happen if the user pressed a button to call a different function in the same script file?
To make it asynchronous you can use callbacks. Asynchronous here would mean that a section of code in the callback would ‘wait’ for an event before being called but a new thread is not created.
What is it about being an Object that makes JavaScript callbacks asynchronous?
It is the same as waiting for an event?
It is true that with Javascript, if you are going to call into a database, generally you must wait for the database to respond (ie, a round trip to Pluto) before your code will continue to execute. This is called a 'blocking' call.
What a callback allows you to do is make a blocking call, but as you do so also say, "Execute this code when the blocking call concludes, but don't wait around for that to happen." Thus, your program continues execution. When the blocking call completes, the code you specify in the callback (which has not been run yet) will then execute. This may be almost immediately or some time later.
With Javascript, the rest of your code will complete execution, then the first callback to be triggered by a blocking call finishing will be executed, and so on until all callbacks are executed. At that point the thread will be shut down.
Note that only the callback code is 'waiting for an event'.
Thus, the execution order looks something like this:
Execute some code.
Set up callback code.
Execute blocking call.
Execute remainder of code.
Wait for blocking call to return.
Execute callback code.
Stop thread process.
Related
I was just reading an article about asynchronous programming and the event loop. During the read he describes that if I call an asynchronous method and pass it a callback, e.g. an Ajax request, the web API will deal with an event. The event in this case would be the Ajax request receiving a message. When the event is raised it is added to the event queue and when the call stack is empty and the event queue are being called, the callback from the event is called.
Given that the callback of the event queue is placed onto the call stack, which is on the UI thread, would that not mean that having a substantially long callback would result in the UI being blocked? Was asynchronous programming not meant to prevent these types of problems?
Edit: I just realized I could test my theory by opening the browser and testing it myself by creating,
setTimeout(function(){
while(true){}
}, 500)
When typing this, the UI will freeze.
Does this imply I am correct? An asynchronous call and asynchronous code can still freeze the UI?
Yes, your intuition is correct.
Because javascript is single-threaded, any work done during a turn of the event loop will block the UI.
The advantage of async calls like Ajax, is that your script doesn't actually need to do any work while it waits for a network response. It is better to yield control while waiting, freeing the UI until the Ajax call comes back and then you can do something.
As an example, you can send an Ajax request in sync mode, and it will block while waiting
Asynchronous code will eventually execute on main thread. So while the asynchronous code will be executing on main thread, main thread will freeze. That means no other code can run. Asynchronous code will not start to execute right away. It will wait until it's time has come, and when the time comes for the asynchronous code to execute it will execute in synchronous manner.
Let me come to the example you have provided.
setTimeout(function(){
while(true){}
}, 500)
The callback you have provided to setTimeout will not execute before 500 millisecond have passed. When the waiting time will over, javascript engine will load the callback function to main thread for executing. As it is an infinite loop, main thread will be blocked for infinite amount of time. No other code will have any chance to be executed.
I was researching about javascript's async behaviour despite being single-threaded and I came after a comment stating that for this code:
request(..., function (error, response, body)
console.log('foo);
});
callAComputationallyIntensiveSynchronousFunctionThatTakesSixHoursToExecute();
console.log('bar');
'bar' will still come before 'foo' because Javascript always finishes the currently executing function first. An event will never interrupt a function.
I understand that a synchronous function execution has a higher priority over events, but I don't understand why 'bar' will be printed before 'foo'. From my reading, the async call should be made, and after that to fill the dead time before response is ready, it goes on and processes the other lines of code until it is ready, and then it should execute the callback function for the response and after that return to processing the code and so on.
The example above however states that even if the response would be ready long before the synchronous function finishes from executing, it still goes on and execute the next line of code. Why is that?
In JavaScript, everything is a function. There is no differentiation between a synchronous and an asynchronous function.
The only difference is the way you call these functions. So "sync"/"async" is an abstract concept for programmers which makes it easier to communicate.
How JavaScript actually works:
JavaScript has a queue of "functions" that are waiting to be executed. Everytime you create a new "asynchronous function", you add it to this queue. This happens, for example, when you do a setTimeout(), an ajax call, or simply a DOM-event like "onClick" triggered by the browser.
If a specific function is executed in JS, it will never be interrupted - it runs until it finished (returned). Only afterwards, the runtime (browser) takes a look at the queue, decides which function should be executed next, and then calls it - waiting it to be finished.
In your example above, the browser is currently executing the function that will print "bar". This execution cannot be interrupted before it finished, therefore "bar" is printed first. During the execution, however, a new asynchronous function is created and pushed to the execution-queue. Only after "bar" has been printed, the runtime will look in the queue, find the "foo"-function and execute it.
A negative side effect of this are long-running tasks. While such a function is executed, nothing else can be done by the browser. Not even rendering/updating the page. So if you have a piece of code that runs for, say, 10 seconds, the user cannot interact with the website until the function finished. The reason for that is that all user events, like mouse movenent, clicks and scroll events are queued and cannot be handled until the thread finishes the long running Task.
Multithreading with JavaScript
With HTML5, JavaScript now has the opportunity to use multiple threads using web workers though. But this is an entirely different topic and out of scope for this question. Just remember that it is theoretically possible.
"When there's nothing to do, check the queue. But only check the queue
when there's nothing left to do."
~ Javascript (https://www.youtube.com/watch?v=vMfg0xGjcOI)
So from what I understand, it basically means that you're delaying execution. Something like
SomeAsynchronousFunction();
SomeRegularFunction();
SomeOtherRegularFunction();
just means that you're essentially rearranging the tasks to
SomeRegularFunction();
SomeOtherRegularFunction();
SomeAsynchronousFunction();
in terms of how the bodies of the three functions are executed. Except that, if your browser/hardware supports parallel computing, and if the body of SomeAsynchronousFunction does not have any dependency on the other two functions, that it will be executed in parallel with the other two functions. Is that right? Or am I totally confused?
You're pretty close. But usually there will be some parts of SomeAsynchronousFunction that are synchronous, and those will be executed immediately -- it's only the completion of the function that's async. For instance, it might perform an AJAX call, so it first creates the XHR object, collects the parameters into a FormData object, and calls xhr.send() immediately; the asynchronous part is the execution of the onreadystatechange callback function, which happens when the server responds and the event processing loop has nothing else to do. So the actual order of execution is like this:
synchronous parts of SomeAsynchronousFunction();
SomeRegularFunction();
SomeOtherRegularFunction();
callback function from SomeAsynchronousFunction();
Javascript runs on a single thread, is non-blocking and uses what's called an event loop so your functions run in the original order, but the asynchronous calls, when they return add another message to the event loop and get executed when all other preceeding messages in the event loop are processed. For more info, I recommend reading this article from the Mozilla Developer Network, Concurrency model and Event Loop
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?
Very simple question: suppose I have the following js/jquery code
doSomething();
$.get(url, callback);
doSomethingElse();
I understand that right after the GET request is sent doSomethingElse() starts being executed. Now suppose that the server's reply arrives while doSomethingElse() is executing. What happens?
Does the callback run in a separate thread in parallel to doSomethingElse()?
Does the execution of doSomethingElse() pause until the callback runs and returns?
Does the callback only get called once doSomethingElse() has returned?
Thank you for any insight!
lara
No, JavaScript in web browsers is single-threaded, by design. That means that although the ajax call may start immediately (and be processed by another thread in the browser), your callback won't happen until the JavaScript interpreter is next idle. Things to do get queued up waiting for the interpreter to become idle and process them.
Edit Answering your specific questions:
Does the callback run in a separate thread in parallel to doSomethingElse()?
No, the callback will run in the same logical thread as doSomethingElse. (It would be implementation-dependant whether that's the same actual underlying OS thread, but you have no way of knowing and you don't care; logically, it's the same thread.)
Does the execution of doSomethingElse() pause until the callback runs and returns?
By default, the get will be asynchronous, so no. doSomethingElse initiates the request, but then continues. (It's possible to do a synchronous get via the underlying XmlHttpRequest mechanism, but it's a very bad idea -- tends to lock up the UI of the browser completely while the request is running, which is ugly -- and I don't know how you do it with jQuery.)
Does the callback only get called once doSomethingElse() has returned?
With an asynchronous get (the usual kind), you can be certain that doSomethingElse will finish before the callback gets called, yes. This is because the JavaScript interpreter will only do one thing at a time, and it doesn't switch to doing a new thing until it's done with the current one. So although doSomethingElse triggers the get (and the get may be processed by other, non-JavaScript threads in parallel to JavaScript), your callback won't happen until after the interpreter is done with doSomethingElse and anything that called it.
I wouldn't be surprised if at some point we start getting multiple threads in browser-based JavaScript, but if and when we do, it'll have to be explicit, since we all happily assume one thread for the moment.
To all intents and purposes there are no threads in JS, therefore execution does not happen on a separate thread.
What web APIs do do is make use of asynchronous callbacks, and that's what is happening here -- get() returns immediately, your callback function will be called once the load is complete and there is no other JS code running.
No, there is only one thread of control for Javascript. The currently executing function will continue running until it completes, then the callback will be invoked once it is ready.
So to specifically answer your question, the callback only gets called once doSomethingElse() has returned. Assuming, of course, that the GET request is successful - if an error occurrs then the callback will never be executed.
Here is a pretty good article that illustrates how this works.
http://www.javascriptkata.com/2007/06/12/ajax-javascript-and-threads-the-final-truth/
I honestly don't know the answer, but I wouldn't place any code in doSomethingElse() that is dependent on something that callback() does. I know that doSomethingElse() will always run first, but as far as timing/thread issues I'm not sure.