Reputation: 12718
I've read Why do I have to use await for a method to run asynchronously. What if I don't want to wait for the method to finish before continuing? and Are callbacks always asynchronous? and am still trying to understand when a callback is actually asynchronous.
For example, doThat
will need to wait for GET
data before doing anything with it. And as the second link above states, javascript is single threaded.
doThis(doThat);
function doThis(callback) {
$.get('http://some_api/some_resource', function (data) {
callback(data);
});
};
function doThat(data) {
// Do something with data
};
The only truly async functionality I've seen is with promises and multiple promises where I can, for example, load other data while animations are wrapping up. I'd like help better understanding when traditional callbacks are actually asynchronous. Concrete examples help.
Upvotes: 2
Views: 534
Reputation: 113974
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?
Upvotes: 2
Reputation: 198426
Starting with the definition:
Asynchrony, in computer programming, refers to the occurrence of events independently 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.
-- Davies, Alex (2012). Async in C# 5.0, via Wikipedia on Asynchrony (computer programming)
In case of JavaScript, it works like this (simplified): There is a queue of tasks waiting to be executed by the main (and only) thread. When you load a script, it is a task placed on this queue. A task runs until it exits, and no other task can interrupt it. However, a task can cause other tasks to be placed on the queue. When one task finishes, the next task on the queue starts. If the queue is empty, the first task that enters the queue afterwards gets immediately executed.
The main ways for tasks to enter the queue, besides being the main task of script being parsed and executed: triggering an event will place handlers registered for that event on the task queue, and reaching a time scheduled by setTimeout
or setInterval
will place the associated task on the task queue.
In JavaScript context, everything that executes within the same task ("main program flow") is said to be synchronous. Everything that is executed in a future task is called asynchronous. Another way to tell is - if the next statement executes before the callback, it is asynchronous; if the next statement executes after the callback, it is synchronous.
$.get(opts, callback)
is an asynchronous call, because the task that executes the function callback
will be placed on the task queue when triggered by the onreadystatechange
event. If you have a statement following it, it will get executed first; it is only after that task finishes, that the task which entered the task queue because of an update to your AJAX call will have a chance to run.
In contrast, $.each(collection, callback)
is a synchronous call, because callback
will be directly called from the each
function, without exiting the current task, and will not generate any additional tasks (not by itself anyway, callback
of course can generate additional tasks). The next statement will have to wait until each
finishes iterating over every element of collection
.
Note that promises are simply wrappers over this mechanism. Everything you can do with promises, you can do without them, just the code will not be as pretty and legible.
Upvotes: 4