Callbacks & Callback Hell

Mariya Baig
3 min readMar 4, 2024

--

Callbacks & Callback Hell — Mariya Baig

Synchronous & Asynchronous Code

Synchronous code — Synchronous code is executed line by line in the order it appears in the program. Each statement waits for the previous one to complete before executing. This means that if there’s a time-consuming task or an I/O operation, the whole program or function will be blocked until that task is finished.

console.log("Hi everyone!") console.log("How you doin?") console.log("I am a synchronous code, i only run line by line")

Asynchronous Code -

On the other hand, asynchronous code allows multiple operations to be performed concurrently without waiting for each other to finish. It doesn’t block the execution of the program while waiting for a time-consuming task or I/O operation to complete.

In JavaScript, common examples of asynchronous operations include fetching data from a server, reading/writing to a file, or waiting for a timer to expire. A common asynchronous function in JavaScript, setTimeout.

console.log("Hi, i'm number 1") setTimeout(()=>{ return console.log("Hi, ideally i'm number two, but i am running late because of setTimeout") }, 2000) console.log("Hello, i'm number 3 ")

Callback functions

Callback functions are the functions that take another function as an argument and are executed after the completion of a specific task.

function calculate(a,b, callback){ const result = callback(a,b) console.log(result) return result } function addition(a,b){ return a + b } function multiply(a,b){ return a * b } function subtract(a,b){ return a - b } calculate(2,3,addition) calculate(2,3,multiply) calculate(2,3,subtract)

here functions addition, multiply and subtract are callback functions which are given as an argument in the function calculate.

What is Callback Hell or Pyramid of Doom?

Callback hell, also known as “Pyramid of Doom,” is a term used to describe a situation in asynchronous programming where multiple nested callbacks are used, making the code difficult to read and maintain. This occurs when you have a series of asynchronous operations that depend on the results of each other, leading to deeply nested callback functions.

function getAdmission(callback) { setTimeout(() => { const admission = "🎓" console.log("Here is your admission letter", admission) callback(admission) }, 2000) } function enrollClasses(admission, callback) { setTimeout(() => { const timetable = admission + "📚" console.log("Here is your timetable for classes", timetable) callback(timetable) }, 2000) } function learnCoding(timetable, callback) { setTimeout(() => { const coding = timetable + "💻" console.log("Here is your coding certificate", coding) callback(coding) }, 2000) } function createResume(coding, callback) { setTimeout(() => { const resume = coding + "📄" console.log("Here is your final resume", resume) callback(resume) }, 2000) } getAdmission((admission) => { enrollClasses(admission, (timetable) => { learnCoding(timetable, (coding) => { createResume(coding, (resume) => { console.log("YOU CAN GET PLACED NOW", resume) }) }) }) })

Each step of the process, from getting admission to being eligible for placement, is handled through asynchronous functions, and each function relies on the completion of the previous one. This creates a nested structure with increasing levels of indentation, forming a pyramid-like pattern. While the example is relatively simple, callback hell becomes more pronounced in larger and more complex codebases, making it challenging for developers to understand and manage the flow of the program. Alternative approaches, such as Promises or async/await, are often employed to flatten the code structure and enhance readability, especially in scenarios involving numerous asynchronous operations.

Originally published at https://mariyabaig.com.

--

--

No responses yet