 In this video, we're going to look at callback functions in JavaScript. Before we go further, I want to talk about why functions are so special, powerful, and sometimes can be confusing in JavaScript. By knowing these things about functions, we can then, you know, understand better and appreciate callback functions. So, first thing is that functions are first-class functions, or sometimes you hear the terms first-class citizens or first-class objects. What does that mean? That means that first-class functions are functions that can be treated or used as variables, like data, right? And because they can be treated like that, that means they are also assignable to a variable we call this function expressions. You've seen this quite often or something like this, where we assign this function, an honest function, to a variable called fx, okay? And then also, functions can be passed as arguments. We call these the inner functions to another function, and that is called the outer function. So, for example, if I have a function called g of x, I can pass this function g of x to f of x like this. So, g of x is now the inner function because it's going to be invoked inside the outer function of x, okay? That is the first-class functions. Functions in JavaScript are also known as higher-order functions because they can operate on other functions. For example, functions can take other functions as arguments, as we see in example C right here. Another feature is that functions can also return a function back as the value. For example, in A here, if I pass g of x to this function f of x, it's going to return the function g of x back to wherever it's being used, okay? So, these two major features of functions are true in JavaScript, and they are quite powerful and very, very useful. And so then, what is a callback function, right? That's our question. So, let's go and take a look at the website over here. I pulled out here on the Mozilla website, and this definition pretty much explains what a callback function is. So, a callback function is a function passed into another function as an argument, which is then invoked inside the outer function to complete some kind of routine reaction. So, a function, a callback function is a function, in this case called greeting, passed into another function, the function processUserInput, right? We pass the greeting function to that as an argument, and this function in greeting is assigned to the callback variable. Of course, this is a function. Now, and we invoke that function inside the outer function here, okay? That's what this means. Now, notice we did not invoke the greeting function here. If you invoke it here, then it's no longer a callback function, because once you invoke it, whatever this function does is the result of that passed to this function, and it may not be a function, it could be just pure data, right? Okay, so let's go back and see some examples and how this works. So, I'm going to go over to this file over here, and I'll do as slow as I can just to make sure this makes sense to you. So, let's create our first function. This will be the callback function. Let's call this function f of x, it takes a data, and for this one, we're just going to return a message saying something like, my name is, and then we're going to add the data to the end of that and we turn that statement back, okay? So, let's have another function here. This is the g of x. This one here takes a data as well, and let's say this data is an array, and we want to print the sum of all the elements in the array, okay? So, we can do that by using the reduce function, okay? So, if you are familiar with reduce, so the data, the reduce, the reduce as you can see, it takes a function, a callback function. This callback function looks like this, and it takes two parameters. The first is the total, or we're going to put in here. So, I'll put here the accumulator, which is total, really. The second is the current element in the array. So, we put here cur here, okay? Or cur element, make sure. And then, what you want to do with this function is, you want the total plus the cur element. That is how you do sum. And the result of this will always be added to the total here again for each iteration. That's how reduce work, right? And we don't have the third parameter, the second parameter because we just want to start from the first element in the data array. So, we're going to then return the total back. That's a simple function there, okay? And so, here is our main function. This is the higher, you know, order function. So, let's just call it main, and we take two parameters. One is going to be the data, and second is the actual function. I'm going to call it fn, okay? And inside here, we do something really simple. We're just going to return the invocation of this function. We pass the data to that function, okay? So, now this is our call. So, we're going to call the main function. I'm going to pass to this function a string, say my name, and then I'm going to pass the first function f of x. Notice again, I did not invoke it. If you invoke it, it's no longer valid. So, you have to keep it like that because it'll be invoked inside the main function, okay? And so, if we turn the data back, which is going to be hopefully this string, and I'm going to console all of that to the browser, though, okay? So, let's save this and run our program. I'm going to do a configuration. I'm going to add this to the node. JS, so I save this so I can run this every time. So, now I go and run, and it should be in the terminal. And here, as you can see, the result comes back. This is my name is Christian, okay? Now, you may be wondering, so what is the purpose of this? Because you could bypass this function, instead of calling the function, you could just do something like this, you might say. Well, I mean, instead of calling f of n, I can call the function f of x directly in here, right? Even if I don't provide this, it doesn't matter, but why not do something like that? I still get the same result, as you can see, which is okay, right? You're probably doing this quite often already. Now, what is the advantage of this? So, let's say that this main function only allows you this option to invoke that function. So, if you don't have this option, if you want to invoke g of x, how do you do that, right? So, that means, okay, well, this function doesn't work. You would have to go in here and do some type of, you know, changes. So, for example, I could change this to option. And then here, I have to say, if OPT is equal to, you know, fx, then return that, right? Else, you know, return the g of x data like that. And then when you pass, you pass this as a string to that option. And so, if I see it, you can see that now, I go and run. I mean, I'm going to get that one. If I pass in the g of x, it doesn't work, I have to pass in data. So, for example, let's duplicate this. And I pass in a list of data, one, two, three. And I call it in the g of x and a run, right? You can see that it works in both cases, okay? So, it only works for g of x and f of x. What if I have a third one? What do you do then, right? So, you can see how you can keep adding more stuff to your main function. And eventually, these come very bloated and really, really hard to maintain. So, the callback function resolved this issue very beautifully. So, I don't care about, you know, checking what type it is. All I know is if I pass in the function, I can invoke it in here, okay? So, you can see that now, if I go back and just change that to the function name. I pass to there as the argument. And the result will come out very beautifully just as this. Okay. All right. That is the advantage of a callback function. Now, you're limited to just one parameter, of course. You can always design this so that it has more parameter, use things, spread operator. But let's say if you do have this and you have another function, a more complex function that maybe, you know, has some objects in there. So, let's say we have another function up here. Call it h of x and it takes the object in this case. Okay. What do we want to do with this object? Let's say that I'm going to call this function again. I'll just duplicate this. And I'm going to pass this function, the h of x. The data is going to be an object. And the first one is, let's say a1 is an array of 1, 2, 3, 4. The second is also going to be an array of 5, 6, 7. And then I'm going to pass in the function. I want to pass in the g of x function to itself, right, to this parameter. And I'll use this g of x function to add these two arrays together. We turn that to the console. Okay. So now I still use the same main function, one parameter for the data. The h of x function here invoke the data here. Once the data goes here as an object, then it's really up to me how to, you know, operate this h of x. So I can do something like, okay, so let data is going to be obj.a1. I'm going to concatenate that first with the obj.a2. So I got my data as an array. And then I'm going to invoke the obj.g of x. I pass to that the data. So I'm invoking this function here, basically. And then I'm going to return the result back. Okay. So now you'll see that it worked just like before. If I return and run it now, I got three results. So the complexity gets, you know, makes it really kind of easier, actually, if you think about it. And if these functions are, of course, reusable, then you can leave it out here. If they are not reusable, it's only for one purpose. You can move that function right in here and just put the function right here as the anonymous function, which is also quite common. Okay. So let me just do one more thing, which is kind of interesting as well. So notice that I have to console log these results to the console. You know, what if you just, you know, you get the result and then you print the result right away. And this is one other option that you can also chain methods to your function as well. So you can do something like the following. Let's say I'm going to go in here and modify my main function. Okay. And now I'm going to return that. I'm going to invoke my function in here. Let's say we're let data or just use the same data. Data is equal to the f of n dot data. So I got the result right itself. I got the result here. And then I'm going to add a property called done. This is going to be assigned to a function. This function will take one parameter. I'll just call this the f, call it g of n for another function. And this function will what all it does is basically, well, you know, instead of g and let's just call it callback or something. Okay. It's a callback function. And all it does is we're just going to return the invocation of this callback function. We pass the data to that. Now this data is really this data. Let's maybe we call it new data or something. Let new data. Isn't that too confusing? I pass this new data to the function. Now, when I pass this callback function from the done property, after you invoke this function first, I know it's confusing but you see. So now, so instead of doing this way, I'm going to remove this. And then I will change that to the end of this function, the done method. Okay. So now I'm calling, I invoke this part first. I got the result back. And then now I'm going to pass to this done method here, which is changed here now. And then what I need, I need a callback function. So this is a callback function. As you can see, it's called a function. And when I return it, as you can see, it takes one parameter. So I need to receive a parameter. I call it data. And then this function, all it does is maybe just say, console log, result, and then we'll put the data here. Okay. So all it does is print the result to the console. Oops. Okay. So these two are no longer working because the way this is done. So I'm going to, I'll leave it as you can see, but it's not going to be working when you run it now. Yeah, let's, let's turn this off. This won't work. And, oh, I forgot to return it. You have to return the function back. We turn the function back as the function back to this main function. So here we go, you get the result. It says the result is the actual data returned. So now what I did was basically we moved the console log and, you know, change a property to the function f of n that is been returned when I call this function. So this part here really is the same as f of x. Because I pass in f of x, it goes in here. I return the same function back. So this whole thing is actually f of x. And you can see that if I do this, f of x is done. And I put here data is equal to console log. We'll here f of x. So you can see the data, right? They, they have produced the same result basically. We'll see that here. Okay. So as you can see, it's the same thing because I call that here. And if you don't want that, then you make this the anonymous function, then this won't work anymore. Okay. So you can do the same here. I can also change this to the done function. I get the result back as well. So you can see the power of callback function being used this way. This one takes a little while to, you know, kind of wrap your head around it. But this is quite powerful. So now with this set, let's go and take a look at something that's more practical, something you might already seen a million times in your code. So here is the HTML that really just has a button. And the output looks like this, a button here. When I click the, you know, button, it's going to call and put some data to the console. And I'm going to use that something you are familiar with called the event listener. So here I can go in here at a constant btn is equal to document.getElementByD. The ID is, I think I called it. Click me. Okay. So click me. And there it is. I target that now to add event listener. We do btn.addEventListener takes the click event. And this is the callback function right here. So again, this is a callback function. You can put it here for event if you want to, you don't have to put it. And then this function is invoked by this function at event listener when you click this button. Otherwise, you just stay there. So this being called at a later time, whenever you need it. So here, let's say we're going to just console log to the message. You clicked me. Okay. Very simple like that. You've probably seen this again, just to make sure it does work. And then there it is, you get the message. Okay. So I do one more example and it will be done with this video. So here I have a data called JSON.data. Let's say I want to get this data using an Ajax call. So I'm going to do writing here. Okay. I'll use the fetch method. I'm fetching the data.json. You've probably seen this already. And you can see that it changed to a then function and then another then function. And then you can also catch the error here. Okay. You see the chaining method here. So this function when you call this, it's going to fetch the data asynchronously. And it's going to invoke either this or this. Okay. This one here is dependent on this one. If this is successful, then it will invoke this one. If there's no successful result that is going to skip off both of these and call this instead. So the then function here takes a callback function. Like I did here, right? It takes a callback function just like this callback function. And it does something and returns the data back for this one. The first then here, it takes a callback function every turn a response. And so you're basically going to return the response in a different format of the data that contains in the body. This one here is like coming back from the back end. If you're familiar with Node.js application development, this is like how you send the data back to the browser through the response.json function. Okay. If you want to return as a text, you put text here. Okay. So that means you're going to fetch the data, return this as the JSON. So I want to use JSON. And then now it's going to trigger the next then function. This then receives the actual data, the result. And we can then just console log to the browser console. So you can see if it fails, then we're going to call this function. It's going to receive a data, usually error message. And you can console log that to the browser as well. Put here error and it will pass in the error message. Okay. Put here just like that. Maybe here we'll put here success. Okay. So here we go. And let's save this, go to the browser and see what happens. So here we go. And it goes really quick. Yeah. Here we go. You see that it loads the first console and it's a success. So we're able to retrieve the data coming back beautifully. You can do it again. Okay. Now what if I go back in here and accidentally alter my file, put a comma here, which is no longer a JSON file. You can see it's red thing here. And then when I try to fetch it on the browser, you can see that we get the error, which is the catch one instead. It tells you what the error message is. So that is the power of callback function, guys. And again, this is asynchronously. Okay. How do you know that? Well, you can do something like this, you know, before the fetch. You can go here and type in something, you know, say console log done, right? And if I go back, you would see that done is printed before the fetch, right? Even though my code was actually coded in a different order. So this is asynchronously. This and this are synchronous. But anyways, I want to just show you that usually these callback functions are very common and very popular in asynchronous calls such as this. This is a function, okay, that is sent to the then function. The then function invoke this function returns back the data. And so you can process the data here, whatever it is, same thing here and here. Okay, if you look at other web APIs like promises, Ajax, many others have this very similar structure. So now that you understand how callback functions work, they can be really useful and functions in JavaScript are always first class in higher order. Thank you for watching. Any question you may have here free to post here or any recommendations also are welcome. Thank you so much. And I'll see you in the next video.