Are all javascript callbacks asynchronous? If not, how do I know which are?
I'm curious as to whether all javascript callbacks are asynchronous
No. For instance, the callback used by Array#sort
is not asynchronous, nor is the one used by String#replace
.
The only way you know whether a callback is asynchronous is from its documentation. Typically, ones involving requests for external resources (ajax calls, for instance) are asynchronous, and others may or may not be.
However, for example, I know that jQuery's AJAX functions are truly asynchronous...
Not necessarily, as currently jQuery still has the async
flag which you can set false
to force a synchronous request. (It's not a good idea, and they're going to remove that, but you can. jQuery passes the flag to the underlying browser object which provides the synchronous/asynchronous behavior.)
What is it that make jQuery's AJAX asynchronous?
The browser. jQuery's ajax calls use the XMLHttpRequest
object (or in certain situations, a script
element), which defaults to asynchronous operation provided by the browser.
Or is there some way to make one's own function truly asynchronous without leveraging very specific functions of the environment...
Until recently, no. Up through the 5th edition specification, JavaScript the language was basically silent on the entire concept of threads and asynchronicity; it was only when you got into environments that it came up. The only way to make something asynchronous was to use a host-provided function, such as nextTick
(or any of the various operations that completes asynchronously) on NodeJS or setTimeout
on browsers.
In the ECMAScript 6th edition specification in June 2015, they introduced promises into the language. The callbacks hooked up to an ES6 promise via then
and such are always invoked asynchronously (even if the promise is already settled when the callback is attached), and so JavaScript has asynchronicity at a language level now. So if you implement your function so that it returns a promise rather than accepting a callback, you'll know that the then
callbacks hooked up to it will be triggered asynchronously.
How to know if a Javascript Callback is Synchronous or Asynchronous?
You have several questions here, so I'll try to answer them one by one:
Is it by default in Javascript or Node.js all callbacks are synchronous unless you do something like setTimeOut or process.nextTick?
In the browser you can kinda have this as the rule of thumb: Only setTimeout
, setInterval
, requests and events are asynchronous. Other built-in callbacks (like Array.prototype.map
) are synchronous.
On Node.js it's more complicated: e.g. you can do file reading both synchronously and asynchronously. Then you just need to know that the callback is asynchronous by nature.
Can I check if there is a way to know if the above callback is Synchronous or Asynchronous?
Unfotunately without checking the source code of the method/function you're calling you cannot know if it's synchronous or asynchronous.
I am guessing it is Synchronous above because it has to wait till the "slow" animation is over before the alert comes up.
Exactly. You can find this from jQuery's documentation for .hide
method:
complete
Type: Function()
A function to call once the animation is complete, called once per matched element.
Why are callbacks considered asynchronous if we need to wait
I can, for example, load other data while animations are wrapping up.
This is exactly what you can do with your code. Note that you can run other code (and indeed the "running other code" is what confuses people) while waiting for doThat
to execute. Exactly like your animation example:
function doThis(callback) {
$.get('http://some_api/some_resource', function (data) {
callback(data);
});
};
function doThat(function (data) {
// Do something with data
});
function doAnotherThing(function (data) {
// Do something with data
});
doThis(doThat);
// without waiting for doThat to run, you can IMMEDIATELY call:
doThis(doAnotherThing);
// without waiting for either doThat or doAnotherThing you
// can output some pretty animations:
setInterval(do_animation,100);
// and without waiting for any of the above you can do anything else:
document.body.innerHTML += 'hello';
Note that what confuses most people is that the document.body.innerHTML='hello'
part runs BEFORE any of the code above it. Which means that the callbacks are asynchronous because they get executed when data arrives, not when the function is called.
Note that not all callbacks are asynchronous. For example, Array.prototype.forEach()
is synchronous:
document.body.innerHTML += 'before<br>';
['hello','world'].forEach(function(x){
document.body.innerHTML += x;
})
document.body.innerHTML += '<br>after';
What determines weather a callback is asynchronous or synchronous is the function that calls it. See also: I know that callback function runs asynchronously, but why?
How to identify if a callback is going to be executed synchronously or asynchronously?
You cannot really tell by looking at the function invocation. Some callbacks are asynchronous, others are not. You will need to check the docs, it will should be stated there.
Often you can tell them apart by the function's signature. If a callback is expected to be called only once with the result of a computation, and neither the callback nor the function don't return anything, the callback is usually invoked asynchronously (setTimeout
, readFile
etc). If the function returns the result immediately, the is typically callback invoked multiple times synchronously (Array::sort
, Array::map
) and yields valuable values. Of course, the exception proves the rule, and sometimes you cannot tell easily, e.g. setInterval
vs Array::forEach
(both return nothing, and invoke the callback multiple times).
I know that callback function runs asynchronously, but why?
There is nothing in the syntax that tells you your callback is executed asynchronously. Callbacks can be asynchronous, such as:
setTimeout(function(){
console.log("this is async");
}, 100);
or it can be synchronous, such as:
an_array.forEach(function(x){
console.log("this is sync");
});
So, how can you know if a function will invoke the callback synchronously or asynchronously? The only reliable way is to read the documentation.
You can also write a test to find out if documentation is not available:
var t = "this is async";
some_function(function(){
t = "this is sync";
});
console.log(t);
How asynchronous code work
Javascript, per se, doesn't have any feature to make functions asynchronous. If you want to write an asynchronous function you have two options:
Use another asynchronous function such as
setTimeout
or web workers to execute your logic.Write it in C.
As for how the C coded functions (such as setTimeout
) implement asynchronous execution? It all has to do with the event loop (or mostly).
The Event Loop
Inside the web browser there is this piece of code that is used for networking. Originally, the networking code could only download one thing: the HTML page itself. When Mosaic invented the <img>
tag the networking code evolved to download multiple resources. Then Netscape implemented progressive rendering of images, they had to make the networking code asynchronous so that they can draw the page before all images are loaded and update each image progressively and individually. This is the origin of the event loop.
In the heart of the browser there is an event loop that evolved from asynchronous networking code. So it's not surprising that it uses an I/O primitive as its core: select()
(or something similar such as poll, epoll etc. depending on OS).
The select()
function in C allows you to wait for multiple I/O operations in a single thread without needing to spawn additional threads. select()
looks something like:
select (max, readlist, writelist, errlist, timeout)
To have it wait for an I/O (from a socket or disk) you'd add the file descriptor to the readlist
and it will return when there is data available on any of your I/O channels. Once it returns you can continue processing the data.
The javascript interpreter saves your callback and then calls the select()
function. When select()
returns the interpreter figures out which callback is associated with which I/O channel and then calls it.
Conveniently, select()
also allows you to specify a timeout
value. By carefully managing the timeout
passed to select()
you can cause callbacks to be called at some time in the future. This is how setTimeout
and setInterval
are implemented. The interpreter keeps a list of all timeouts and calculates what it needs to pass as timeout
to select()
. Then when select()
returns in addition to finding out if there are any callbacks that needs to be called due to an I/O operation the interpreter also checks for any expired timeouts that needs to be called.
So select()
alone covers almost all the functionality necessary to implement asynchronous functions. But modern browsers also have web workers. In the case of web workers the browser spawns threads to execute javascript code asynchronously. To communicate back to the main thread the workers must still interact with the event loop (the select()
function).
Node.js also spawns threads when dealing with file/disk I/O. When the I/O operation completes it communicates back with the main event loop to cause the appropriate callbacks to execute.
Hopefully this answers your question. I've always wanted to write this answer but was to busy to do so previously. If you want to know more about non-blocking I/O programming in C I suggest you take a read this: http://www.gnu.org/software/libc/manual/html_node/Waiting-for-I_002fO.html
For more information see also:
- Is nodejs representing Reactor or Proactor design pattern?
- Performance of NodeJS with large amount of callbacks
Callback of an asynchronous function is never called
The callback isn't getting called because the only thread that can call it is tied up doing your infinite loop.
In browsers, JavaScript runs on a single main UI thread (plus as many web workers as you want to create). That thread runs on a job queue: It picks up a job to do (for instance, processing a click), does the job, and then yields back to wait for the next job. You're blocking that one thread with the infinite loop. The timer schedules the callback in the job queue (probably, that's implementation-specific), but the thread never finishes the current job (the one that called your infinite loop) and so it never picks up that next job.
NodeJS also runs your code in a single thread and so does the same thing. (Not all environments do, but I'm not aware of any with setTimeout
that don't schedule the timer callback on the same thread that requested it.)
Function only after all asynchronous callbacks are completed in if statements
You can use Promise.all
:
var promises = [];
if (this.originalFrom > addFrom) {
promises.push(this.dataService.addTimeSlots(details));
}
if (this.originalTo < addTo) {
promises.push(this.dataService.addTimeSlots(details2));
} else if (this.originalTo > addTo) {
promises.push(this.dataService.addTimeSlots(details3));
}
Promise.all(promises).then((result) => {
console.log(result);
}, (err) => {
console.log(err);
});
Related Topics
Iterate Through Nested JavaScript Objects
Convert Base64 to Image in JavaScript/Jquery
React This.Setstate Is Not a Function
How to Load Data from a CSV File in D3 V5
How to Be Notified When an Element Is Added to the Page
Ajax Jquery Refresh Div Every 5 Seconds
Why Element.Style Always Return Empty in Js
Run Change Event for Select Even When Same Option Is Reselected
How to Get the HTML of a Div on Another Page with Jquery Ajax
How to Download a File Using Window.Fetch
Convert Column Index into Corresponding Column Letter
Disabling and Enabling a HTML Input Button
Why Does JavaScript Object Show Different Values in Console in Chrome, Firefox, Safari
How to "Await" for a Callback to Return
Removing # from Url in Angularjs While Having .Run in Routes
How to Use JavaScript to Dynamically Change a Video's Source