Usage of callbacks

What is the point of callbacks? take this asynchronous code for example:

console.log("Start");

function loginUser(email, password) {

  setTimeout(() => {

    console.log("now we have the data")

    console.log({userEmail: email})

    getUserVideos()

  }, 3000);

}

function getUserVideos() {

   setTimeout(() => {

     console.log("now we have the videos")

     console.log(["video1", "video2", "video3"]) 

   }, 7000)

}

const user = loginUser("dhbd@goomail.com", 123456)

console.log("Finish");

And here’s another version of the code using callbacks:

console.log("Start");

function loginUser(email, password, callback) {

  setTimeout(() => {

    console.log("now we have the data")

    callback({userEmail: email})

  }, 3000);

}

function getUserVideos(callback) {

   setTimeout(() => {

     console.log("now we have the videos")

     callback(["video1", "video2", "video3"]) 

   }, 7000)

}

const user = loginUser("dhbd@goomail.com", 123456, (user) => {

  console.log(user)

  getUserVideos((videos) => {

    console.log(videos)

  })

})

console.log("Finish");

I cannot see any difference in the output of the two! can you then explain why we use callbacks?
Do they have something to do with customer-server communication or something like that?

In the most general sense, a callback is just a function that you pass to another function for it to use. They are commonly used for async things - “I’m passing you a function, after you’re done, call this function”. They are also used in prototype methods like map - “I’m passing you a function. Apply it to each element and use the returned result from that to the new element in the new array.”

So just to be clear, both examples have callbacks. For example, in your first one this:

() => {
    console.log("now we have the data")
    console.log({userEmail: email})
    getUserVideos()
  }

You are passing that to setTimeout and saying, "I know you’re async and JS won’t wait, so when you’re done (after the 3000ms), run this function.) It is an anonymous function, but it’s still a function being used as a callback. You also could define it elsewhere.

In the second example, you’ve kind of broken things up a little. That’s fine. You’re passing in part of the functionality of the callback in a function called callback. You also could have passed all of that in and just given setTimeout the function callback (or whatever you want to call it) as it’s first parameter - that would have been a third way to do it.

Why do callbacks? Because they make for clean and flexible code.

Take for example the sort method. You don’t have to pass a callback - it has a default sort method. But what if we wanted something different? What if we want to sort numerically? What if we want to sort by length? In reverse order? What if it is a personnel record and we want to sort by last name, then first name, then DOB? One option would be to create a separate prototype method for every (infinite?) combination. Another approach is to allow the user to pass in a callback and let them define the sort if they want. I like the second approach.

And again, they come in real handy with async operations, “It’s going to take a little time to make that http request and JS won’t wait, so here’s a function to call when you get that data.” Different languages handle it differently, but for JS, this is a common method. We also have Promises, and async/await.

2 Likes

You might also want to give higher-order functions a look (and a Google search).

2 Likes

Im not gonna comment on the specific code you provide, but rather answer the general question of the topic. Like people already said, callback is a function, passed to another function as an argument. And what is the purpose of an argument to a function? Its a value which the function uses and run some actions. So it can behave differently based on what value you pass to it and produce different outcome. Functions that dont take arguments, has the necessary values for their code to operate already available, but there are times when you know how the functions should behave, but you dont have the required values yet, so you put down the function and let it accept the required values, then in your code, you call it once you have the needed values. From here on, you can assume when a callback can be useful. Its, for when a function can run its code with different callbacks, or you dont have the callback available yet. For example, you design a function which purpose is to display calculation between two numbers, while passing the calculations as a callback:

let add=(a,b)=>(a+b)
let multiply=(a,b)=>(b*a)

let displayCalculation=(a,b,callback)=>{
  console.log('The first number is: '+a)
  console.log('The second number is: '+b)
  console.log('The result of the calculation is: '+callback(a,b))
  console.log('Guess the operation!')
}

displayCaluclation(2,3,add)
displayCalculation(5,3, (a,b)=>a-b)
1 Like