Asynchronous JavaScript using Callbacks

Understanding Callback Functions

Mithilesh Kr. Patel
3 min readJan 7, 2024

JavaScript is a synchronous, single threaded programming language but with the help of Callbacks, Event Loops and Promises it can perform asynchronous operations.

Synchronous means in order or in sequence and Single-threaded means it has only one call stack and one memory heap. This single thread means that JavaScript can only execute one operation at a time, and any additional tasks have to wait until the current task is completed. It also means that if a function takes a lot of time to execute, it may block the execution of the next tasks which is undesirable.

Callbacks are very important and play an important role in Asynchronous operations in JavaScript. In this article, we will see what are callback functions and how are they used.

A callback function is a function that is passed as an argument to another function and is executed after some kind of event.

This often occurs in asynchronous operations, where a function is called to perform some task, but the result of that task is not immediately available. Instead of waiting for the result, the program continues executing, and when the result is ready, the callback function is called to handle the result.

// Function that takes a callback
function greet(name, callback) {
console.log('Hello, ' + name + '!');
callback();
}

// Callback function
function sayGoodbye() {
console.log('Goodbye!');
}

// Calling the function with a callback
greet('John', sayGoodbye);

The the above example we see how a function greet can accept another function (sayGoodbye) as an argument and call it as a callback after performing its primary operation, in this case, greet logs a greeting message to the console and then calls sayGoodbye to log a farewell message.

Uses of Callbacks in Asynchronous operations

JavaScript is a synchronous single-threaded programming language but with the help of callbacks, Event Loops and promises it can perform asynchronous operations.

When the callbacks are called they are added to the callback queue. Now it’s the responsibility of the Event loop to push functions from the callback queue into the call stack. The Event loop continuously checks the Call Stack to be empty and once it’s empty it pushes the first item in the callback queue to the call stack.

The JavaScript Asynchronous Event Loop with Web APIs
The JavaScript Asynchronous Event Loop with Web APIs, Byteslovesbits, CC BY-SA 4.0, via Wikimedia Commons

Callbacks in setTimeout()

Someone with any experience in JavaScript might remember the setTimeout() function. It is a WebAPI which takes a callback function and calls it after a specific delay as the second parameter (in milliseconds).

setTimeout(function sayHello() {
console.log('Hello, John !');
}, 2000);

// Output: After 2000ms => Hello, John !

Here we have a function sayHello() which is passed to a webAPI setTimeout. This takes a function to be called after a specific delay. Here it is 3000 milliseconds or 3 seconds. So the function sayHello() is passed into the callback queue after the delay and as soon as the main thread of JS or the Call Stack is empty it is executed.

Event Handling

// Adding an event listener with a callback function

document.getElementById('myButton').addEventListener('click', function() {
console.log('Button clicked!');
});

In this example, the addEventListener() function takes an event as the first and a callback function as its second argument. This function resides in the browser’s memory until the event is fired. When the event is fired, in this case, the button with the ID myButton is clicked, the callback function is pushed into the callback queue and from there the Event Loop which is continuously checking the Call thread pushes it into the Call Stack.

--

--

Mithilesh Kr. Patel

Tech enthusiast and developer sharing my thoughts on software engineering, career growth, and staying productive. Let's level up together!