Let's talk about JavaScript Asynchronous

2018-02-27

The difference between Synchronous and asynchronous code

Synchronous code

If you have two lines of code (C1 followed by C2), then C2 cannot begin running until C1 has finished executing.

Asynchronous code

If you have two lines of code (L1 followed by L2), where L1 schedules some task to be run in the future, but L2 runs before that task completes.

But remember: That asynchronous does not mean the same thing as concurrent or multi-threaded. JavaScript can have asynchronous code, but it is generally single-threaded. This is like a restaurant with a single worker who does all of the waiting and cooking. But if this worker works quickly enough and can switch between tasks efficiently enough, then the restaurant seemingly has multiple workers.

Let see some examples

1
2
3
4
5
6
// Say "Hello."
console.log("Hello."); // Say "Goodbye" two seconds from now.
setTimeout(function() {
console.log("Goodbye!");
}, 2000); // Say "Hello again!"
console.log("Hello again!");

The output is Hello! Hello again! (Wait for two seconds) Goodbye!

Because the call back function will be put in the event loop, wait until all the tasks are finished in the thread, and then excute the tasks in the event loop.

Jump into Ajax requests

1
2
3
4
5
6
7
8
function getData() {
var data; $.get("example.php", function(response) {
data = response;
});
return data;
}
var data = getData();
console.log("The data is: " + data);

Similar to setTimeout in the example above, $.get does not pause the execution of the code, it just schedules some code to run once the server responds. That means the return data; line will run before data = response, so the code above will always print “The data is: undefined”.

So, what we can do?

Asynchronous code needs to be structured in a different way than synchronous code, and the most basic way to do that is with callback functions.

In JavaScript, we can create a callback function that we pass in to an asynchronous function, which will be called once the task is completed.

That is, instead of

1
2
var data = getData();
console.log("The data is: " + data);

we will pass in a callback function to getData:

1
2
3
getData(function (data) {
console.log("The data is: " + data);
});

Of course, how does getData know that we’re passing in a function? How does it get called, and how is the data parameter populated? Right now, none of this is happening; we need to change the getData function as well, so it will know that a callback function is its parameter.

1
2
3
4
5
function getData(callback) {
$.get("example.php", function(response) {
callback(response);
});
}

You’ll notice that we were already passing in a callback function to $.get before, perhaps without realizing what it was. We also passed in a callback to the setTimeout(callback, delay) function in the first example.

Since $.get already accepts a callback, we don’t need to manually create another one in getData, we can just directly pass in the callback that we were given:

1
2
3
function getData(callback) {
$.get("example.php", callback);
}

Callback functions are used very frequently in JavaScript, and if you’ve spent any amount of time writing code in JavaScript, it’s highly likely that you have used them (perhaps inadvertently). Almost all web applications will make use of callbacks either through events (e.g. window.onclick), setTimeout and setInterval, or AJAX requests.


Comments: