Callbacks

In this lesson, you will discover what asynchronous JavaScript is and how to use callbacks.

JavaScript is a single-threaded programming language, which means only one thing can happen at a time. While a single thread simplifies writing and reasoning about code, this also has some drawbacks.

Imagine we perform a long-running task like fetching a resource over the network. Now, we block the browser until the resource is downloaded. This can make for a bad user experience and might result in the user leaving our page.

That’s where asynchronous JavaScript comes into play. Using asynchronous JavaScript, we can perform long-lasting tasks without blocking the main thread.

There are three ways of doing asynchronous JavaScript:

  • Callbacks
  • Promises
  • Async/Await

Before we look into these techniques, let’s try to understand the difference between synchronous and asynchronous code.

Synchronous code

When we execute code synchronously, we wait for it to finish before moving to the next task. Nothing else can happen while each operation is being processed, rendering is paused.

Let’s write some code to clarify:

function logFunction() {
  console.log('in logFunction');
}

console.log('Start');
logFunction();
console.log('End');

// -> Start
// -> in logFunction
// -> End

This code executes as expected.

  1. We log “Start.”
  2. We execute the function which logs “in logFunction.”
  3. We log “End.”

So, synchronous tasks must be aware of one another and be executed in sequence.

Asynchronous code

When we execute something asynchronously, we can move to another task before it finishes.

If you want to know more about what happens under the hood in JavaScript’s asynchronous programming, you can read more about it here:

Let’s look at another example using setTimeout(), which allows us to wait a defined number of milliseconds before running its code:

console.log('Start');

setTimeout(() => {
  console.log('In timeout');
}, 1000); // Wait 1s to run

console.log('End');

// -> Start
// -> End
// -> In timeout

Did you expect “In timeout” to be logged before “End”? We are not blocking the code execution. Instead, we continue and come back to run the code inside setTimeout one second later.

Let’s look at another example. When we fetch an image from a server, we can’t return the result immediately. This means that the following wouldn’t work:

let response = fetch('myImage.png'); // fetch is asynchronous
let blob = response.blob();

This is because we don’t know how long the image takes to download. Therefore, when we run the second line, it throws an error because the response is not yet available. Instead, we need to wait until the response returns before using it.

Let’s look at how we would solve this with asynchronous code.

Callbacks

This approach to asynchronous programming is to make slow-performing actions take an extra argument, called a callback function. When the slow action finishes, the callback function is called with the result.

As an example, the setTimeout function waits a given number of milliseconds before calling a function. We can simulate slow asynchronous tasks without calling the backend this way:

setTimeout(() => console.log('One second later.'), 1000);

While the concept of callbacks is great in theory, it can lead to confusing and difficult-to-read code. Just imagine making callback after callback:

getData(function(a) {
  getMoreData(a, function(b) {
    getMoreData(b, function(c) { 
      getMoreData(c, function(d) { 
       // ...
      });
    });
  });
});

Nested callbacks that go several levels deep are sometimes called callback hell. Each new callback level makes the code more difficult to understand and maintain. Using callbacks is not common these days, but if we get unlucky, we might find them in legacy code bases.

Conclusion

When we have code that doesn’t complete immediately, we need to wait for it to finish before continuing. This is where asynchronous JavaScript comes in.

In this lesson, we looked into the differences between synchronous and asynchronous JavaScript and how we first tried solving it with callbacks.

Next, we will look into modern asynchronous JavaScript with promises and async-await.


Quiz on asynchronous JavaScript and callbacks

Get hands-on with 1000+ tech skills courses.