JavaScript Tutorial

Javascript Callbacks

In JavaScript, callbacks are functions that are passed as arguments to other functions and are invoked or executed at a later time or in response to certain events. Callbacks play a significant role in handling asynchronous operations and event-driven programming in JavaScript.

By passing callbacks to functions, we can achieve non-blocking execution and ensure that code is executed in the proper sequence, especially when dealing with time-consuming tasks or tasks that rely on external data or events. Callbacks can be defined as named functions or anonymous functions, providing flexibility and reusability in our code.

Let's look at the following example of an array, where we want to filter out the odd numbers,

let numbers = [1, 2, 7, 3, 4, 6];

To find all the odd numbers in the array, we'll make use of the filter() method of the Array object. The filter() method creates a new array from the given array, based on the test performed by the callback function passed to it.

Let's first define the callback function that checks if a given number is odd,

function findOdd(num){ return num%2 !== 0 }

When we pass a callback function into another function, we just pass the reference of the function i.e., the function name without the parentheses ().

let oddnumbers = numbers.filter( findOdd )

In the above code, we have an array numbers containing various numbers. The filter() method is called on the numbers array and takes a callback function as an argument.

The callback function checks each element of the array and returns true if the number is odd (i.e., not divisible by 2). The filter() method creates a new array containing only the elements for which the callback function returns true.

The resulting array oddNumbers will contain all the odd numbers from the original array. Finally, we log the oddNumbers array to the console.

To shorten it, we can use an anonymous function as a callback, and instead of the above two lines of code, we can do it in one:

let oddnumbers = numbers.filter(function(num){ return num%2 !== 0 })

Input:-

   

Output:-

Synchronous callback functions

Synchronous callback functions are executed sequentially from top to bottom in our code.

In the following example, an arrow function is used as a callback function within a synchronous function. The sort() method completes its operation before the console.log() statement is executed.

Input:-

   

Output:-

Asynchronous callback functions

Asynchronous callback functions in JavaScript allow the execution of the remaining code while waiting for an operation to complete.

JavaScript, being a single-threaded programming language, handles asynchronous operations using the callback queue and event loop mechanism.

For example, when downloading a picture from a remote server, the time taken depends on the network speed and the size of the picture.

The following code snippet utilizes the setTimeout() function to simulate the download() function:

Input:-

   

Output:-

Nesting callbacks and the Pyramid of Doom

Nesting callbacks and the Pyramid of Doom refer to a common coding pattern in JavaScript where asynchronous operations are chained together by nesting callback functions inside one another. This pattern can result in code that is difficult to read, understand, and maintain.

The Pyramid of Doom

The "Pyramid of Doom" is a term used to describe a common coding pattern in JavaScript where multiple asynchronous operations are chained together by nesting callback functions inside one another. This nesting creates an indentation pattern that resembles a pyramid, hence the name.

Here's an example of the Pyramid of Doom pattern:

asyncOperation1(function(result1) {
  asyncOperation2(function(result2) {
    asyncOperation3(function(result3) {
      // More nested callbacks...
    });
  });
});

In this pattern, each asynchronous operation relies on the result of the previous operation, so they are nested inside the callbacks. As more operations are added, the code becomes deeply nested and harder to read and maintain.

The Pyramid of Doom can make code harder to follow, understand, and debug. It can also make error handling more complex and lead to callback hell, where code becomes difficult to manage due to excessive nesting.

 

However, this callback strategy does not scale well when the complexity grows significantly or we have more images required in our project.

Nesting many asynchronous functions inside callbacks is known as the pyramid of doom or the callback hell. To avoid the pyramid of doom, we use promises or async/await functions.

To deal with this situation there are alternative approaches such as Promises and Async/await functions. These alternatives provide more structured and readable ways to handle asynchronous operations, reducing the need for deep nesting and improving code clarity and maintainability.

 

Go back to Previous Course