2

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.

Community
  • 1
  • 1
user3871
  • 12,432
  • 33
  • 128
  • 268
  • 1
    A "callback" is really just a function that you pass as an argument to another function so that the other function can call it, a process that *could* all be synchronous - it really depends what the other function is doing. But even in an asynchronous situation such as with Ajax, it's not the callback function itself that is asynchronous, it is whatever eventually calls it that is asynchronous. In your example, `doThat()` doesn't wait - it is other code that waits to call `doThat()` (also your `doThat()` definition is invalid). – nnnnnn Aug 24 '16 at 04:56
  • You might want to have a look at [Are all javascript callbacks asynchronous? If not, how do I know which are?](http://stackoverflow.com/q/19083357/1048572) for the general question and at [What is a simple example of an asynchronous javascript function?](http://stackoverflow.com/q/13806695/1048572) for examples – Bergi Aug 24 '16 at 04:56
  • Maybe this helps? http://stackoverflow.com/questions/21607692/understanding-the-event-loop – ecarrizo Aug 24 '16 at 04:57
  • @nnnnnn oops on the `doThat()` definition. Fixed – user3871 Aug 24 '16 at 05:24

2 Answers2

4

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.

Amadan
  • 191,408
  • 23
  • 240
  • 301
2

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?

Community
  • 1
  • 1
slebetman
  • 109,858
  • 19
  • 140
  • 171