Handling Async Issues with Callbacks

What is a Callback?

  • Callbacks are functions that are passed to another function

  • We can use callbacks to control the order in which our multiple asynchronous functions are executed

  • The code below modifies our .printLetter() function to accept a callback as a 2nd parameter

function printLetter(letter, callback) { //<- callback function param added
  setTimeout(() => {
    console.log(letter)
    callback() // <- execute (call) the callback param after printing letter
   }, Math.floor(Math.random() * 3000))
}

//... the rest of code below not shown for brevity
  • The changes will result in .printLetter() calling the next function (callback) after it’s done with the current function

  • Now let’s see how we can use this callback approach to control the order in which our asynchronous functions are executed


Example: Using callbacks to control the execution order of async functions

function printLetter(letter, callback) { //<- callback function param added
  setTimeout(() => {
    console.log(letter)
    callback() // <- execute (call) the callback param after printing letter
   }, Math.floor(Math.random() * 3000))
}

/*
Using nested callback structure
to control the execution order
of the async functions
*/

function printAll(){
  printLetter("A", () => {
    printLetter("B", () => {
      printLetter("C", () => {})
    })
  })
}

console.log('Calling printAll function')
printAll()
console.log('End of code')
  • Run the jsbin below and notice that no matter how many times we run the code, our asynchronous functions will be executed in the desired order (“A” -> “B” -> “C”)

JS Bin on jsbin.com

  • However, observe how our .printAll() function is now using nested callbacks to meet our goals

  • The introduction of nesting introduces additional complexity and makes the code difficult to maintain

  • The use of nested callbacks to handle asynchronous code is referred to as “Callback Hell” and should generally be avoided