Callback Functions in JavaScript

A JavaScript callback is a function which is to be executed after another function has finished execution.

A more formal definition would be - Any function that is passed as an argument to another function so that it can be executed in that other function is called as a callback function.

Want a Top Software Development Job? Start Here!

Full Stack Developer - MERN StackExplore Program
Want a Top Software Development Job? Start Here!

Need of Callback Functions

We need callback functions because many JavaScript actions are asynchronous, which means they don't really stop the program (or a function) from running until they're completed, as you're probably used to. Instead, it will execute in the background while the rest of the code runs.

Let us look at a real-world example to understand it (synchronous callback function) better.

A callback's primary purpose is to execute code in response to an event. These events might be user-initiated, such as mouse clicks or typing. With a callback, you may instruct your application to "execute this code every time the user clicks a key on the keyboard."

const button = document.getElementById('button');
function callback(){
console.log("Hello world");
}

button.addEventListener('click',callback);

In the above code, we add addEventListener as a function and we are passing another function callback as an argument. And when a click event is triggered the addEventListener registers the callback function.

Callback_functions_in_JavaScript_1

One More Example! (Asynchronous Callback Function)

If you wanted to download data from a server (which may take long durations of time), it would be wasteful for your program or function to just freeze while you waited for the data to be fetched. Instead, it's common practice to execute the fetching operation in the background.

This implies that if you have two functions in a row, one of which is asynchronous, function B will be performed while the other is still running. If function B is dependent on the data that function A is retrieving, you will run into issues.

async function fetchUsers() {
  const resp = await fetch('<https://jsonplaceholder.typicode.com/users>');
  const users = await resp.json();
  const names = users.map(({ login }) => login);
  console.log(names);
}

An async keyword is placed as a prefix to the function to make a function asynchronous.

The above function fetches fake user data of 10 users. We are then converting it to a json object to extract the user data.

The asynchronous functions return a promise, when the asynchronous function encounters the term await <promise> (notice that fetch() delivers a promise), it stops its execution until the promise is resolved. To read more about promises click here.

An asynchronous callback function differs from an asynchronous function. The higher-order function executes the asynchronous callback function in a non-blocking way. However, while waiting for promises (await promise>) to resolve, the asynchronous function stops its execution.>

We can make this an asynchronous callback by adding it to an event, like a button click.

const button = document.getElementById('fetchusers');
button.addEventListeners('click', fetchUsers);

Callback_functions_in_JavaScript_2.

Learn 15+ In-Demand Tools and Skills!

Automation Testing Masters ProgramExplore Program
Learn 15+ In-Demand Tools and Skills!

Nesting Callbacks and Callback Hell

There are many ways to handle nested callbacks, using async await as discussed above, or using the old school way of promises (read about promises) or splitting the code into different functions.

Using Promises

We must generate a new promise for each callback in order to convert them to promises. When the callback is successful, we may resolve the promise. If the callback fails, we can reject the promise.

function getUserPromise {
  const newUser = getUserFromApi(user)
  return new Promise((resolve, reject) => {
    if (user) {
      resolve(user)
    } else {
      reject(new Error('No more new users!'))
    }
  })
}

Now you can create one more function and call the above function as a callback.

Using Async-Await

We have already seen how to create an asynchronous callback in the above section.

We can write asynchronous functions as if they are synchronous (executed sequentially) with the use of await as it stops the execution until the promise is resolved (function execution is successful).

const userProfile = async () => {
  const user = await fetchUsers(1) // argument indicated number of users to fetch
  const updatedAddress = await updateAddress(user)
  const pincode = await getPincode()
  const updateUser = await updateUser(user, updatedAdress, pincode)
  return user
}

// fetch and update user profile
userProfile()

You can nest these functions in promises as well.

Benefits of Callback Function

Callback functions are needed because many JavaScript actions are asynchronous. Instead, it executes in the background while the rest of the code runs. A callback's purpose is to execute code in response to an event. These events can be like mouse clicks; with callback, we can add text at the end of each statement like"execute this code every time the user clicks a key on the keyboard."

Want a Top Software Development Job? Start Here!

Full Stack Developer - MERN StackExplore Program
Want a Top Software Development Job? Start Here!

Asynchronous Functions and Asynchronous Callback

Asynchronous functions return a promise; when an asynchronous function encounters the term ‘awaits’, it stops execution until the promise is resolved, while an asynchronous callback is a higher-order function that executes the asynchronous callback function in a non-blocking way. While a promise is fixed, the asynchronous function stops its execution. 

When to Use the Callback Function

Callbacks ensure that the function will not run before the task is completed but will run right after the task is completed. It develops asynchronous JavaScript code and keeps them safe from errors. In JavaScript, the way to create a callback function is to pass it as a parameter to another function and then call it back after the task is completed.

There are ways to handle callbacks.

  • Use of Promise: A promise can be generated for each callback. When the callback is successful, the promise is resolved, and if the callback fails, the promise is rejected.
  • Use of Async-Await: Asynchronous functions are executed sequentially with the use of await; execution stops until the promise is revolved and function execution is successful.

Conclusion

We have looked at the what's and why's of callback functions in JavaScript, along with examples using synchronous and asynchronous functions to understand callbacks.

In the end, we also covered what is nested callbacks and how to tackle them using promises and async-await.

To learn more about JavaScript and its amazing features which powers websites, take the Post Graduate Program in Full-Stack Web Development. You can also sign up on our SkillUp platform to improve your software development knowledge. It is a Simplilearn initiative that offers free online courses to help you hone your skills in multiple programming languages, including JavaScript. 

About the Author

Ravikiran A SRavikiran A S

Ravikiran A S works with Simplilearn as a Research Analyst. He an enthusiastic geek always in the hunt to learn the latest technologies. He is proficient with Java Programming Language, Big Data, and powerful Big Data Frameworks like Apache Hadoop and Apache Spark.

View More
  • Disclaimer
  • PMP, PMI, PMBOK, CAPM, PgMP, PfMP, ACP, PBA, RMP, SP, and OPM3 are registered marks of the Project Management Institute, Inc.