From the course: Advanced Node.js

Callback pattern - Node.js Tutorial

From the course: Advanced Node.js

Start my 1-month free trial

Callback pattern

- [Instructor] The think about node.js is it's asynchronous, there's only one thread and how effective our applications are at sharing the single thread across multiple processes is up to us. In this next section, we will review essential techniques and patterns for working with asynchronous code, the first and most basic technique that is core to node.js is the callback pattern. A callback is a block of instructions wrapped in a function so that it can be invoked when an asynchronous operation has completed. Lets go ahead and look at some code. So I'm gonna go into our exercise files under chapter one, under chapter one one and I'm gonna go ahead and grab the start folder and I'm gonna drag that start folder over to my code editor so I'm gonna drag it over to Atom and we will open that folder in Atom. Also go back to the files and drag the start folder over my terminal so that we can open that location in the terminal as well. Now I want the terminal in my code editor to be side by side, I can do so with the mac by holding the green button and then releasing my terminal window on the right side of the screen and then selecting my code editor for the left side of the screen. I'll close out some of these extra files here and we're looking at our first example, the index.js that's within that start folder. I can actually collapse, hide and show the files in the project menu in Atom by holding command backslash, so command backslash will toggle my file menu. So before we can discuss callbacks, let's take a look at some synchronous code. So here we have a little application that has a hide string function and what it will do is it will replace the string that we sent to the function with Xs. So I can come out here to my terminal I'll clear the current screen and then by typing node dot I'm telling node.js to run the default index dot js file within the start folder and I can see my result hello world replaced with Xs. This code is synchronous, the hide string function is executed immediately on the current thread. The result, the hidden string is returned from the function using the return keyword. Returning the result of a function like this is referred to as direct style. Whenever we return a value from a JavaScript function we are working with code synchronously using direct style. So I'll go ahead and just add one more line console dot log and so we know when our program has ended and again I'll go ahead and run this over here in the start folder by typing node dot and we can see that we see the Xs before we see the end being logged to the console. Now direct style is not the only way that we can return values from functions. Let's go ahead and modify the hide string function to pass its value back using something called continuation passing style or CPS. Now to do so, we're not going to use the return keyword, what we're gonna do is take in another function as an argument, so the hide string function is now gonna take in the string and a function that we can use to pass the value of the hidden string back to the consumer. So I'm gonna go ahead and type done and I'm gonna go ahead and surround the results of the string that replaced with the done method so we're actually passing the hidden string back via a function. Now using continuation passing style looks a little bit different, we're gonna get rid of setting hidden equal to what was returned from the function and instead we're gonna capture the hidden variable via the arguments of the function that we pass as the second argument to hide string. So I'll go ahead and move this console log here within this function too. There we go and what you're gonna notice is when we come over to the terminal and then we go ahead and save this. When we come over to the terminal, we're gonna run it and our results are the same so we see our hidden string, hello world, Xed out and we also see end showing up second. You may be saying to yourself, that hide string function looks like its using a callback. This is sorta true but if we wanted to get really technical about definitions, a callback needs to be asynchronous. This code is still operating synchronously. So we're using a function to pass the data back but we're still operating synchronously, meaning that the entire thread has executed in order when we call hide string, the value's passed back to hidden and that is executed immediately. So to have a callback, we actually need to introduce some asynchronicity into our hide string code. Now I can do this by invoking a process dot next tick. So process dot next tick tells node.js to invoke the function that we send to next tick on the next loop. So this is going to be on the next node.js loop and it won't happen synchronously. Let's go ahead and go over here to the terminal window and run our code. And now you can see the word end shows up before the Xs and that's because all of our code is executed and then we're actually passing the results back in the next tick or the next loop. So our hidden string is being logged in the next tick or the next loop after our end string has been logged. So this is a callback, specifically the done function is the callback. Now that the hide string has a done function to handle the results, it can wait to execute that done function whenever it's ready. Because we wait until the next tick to pass the results back to the done function, that's the key that makes it a callback. So now we have to keep track to when specific lines of code execute. We did not want the log hidden until we get a result from the hide string method. Our code no longer executes the order that it appears on the page, it executes when it is ready. As JavaScript developers, it's up to us to keep track of when our code is executing. I'm gonna go ahead and replace the code that we see here, the index, with another example, a delay function. So we will add a delay that we can pass a number in seconds and a callback so within the delay function what we'll do is we'll call a set time out this is another way to introduce asynchronicity into our code and we will invoke the callback function after the number of seconds times 1000. So now, we can actually use this delay method to create some asynchronicity within our code. So console dot log starting delays and then we'll go ahead and use the delay function and we will delay for two seconds and then this callback function will be invoked after our two second delay. And if I save this and clear the terminal and run the same file again so we see starting delays and then after two seconds we see two seconds. So you can see how callbacks can be used to handle asynchronous code. The callback is not invoked until it's ready, until we wait two seconds. Now we can sequentially execute delays using callbacks. All we have to do is further ness delay calls within the callback so I'll go ahead and delay for another second and I'll go ahead and do a log here three seconds and we'll go ahead and be good and put some semicolons in this code even though I typically do not use them. We'll go ahead and add another delay as well we'll delay for another second and console dot log four seconds. Alright there we go so I'm gonna go ahead and save my file and let's go ahead and come to the terminal and run it so we can see we're starting delays we wait two seconds, three seconds, four seconds. So using callbacks we can supply code to execute when something happens. The above code is an example of sequential execution with callbacks. When the first delay has completed, we log a message and execute the next delay. By repeating this pattern, we're able to execute the console logs sequentially when it is time for each log. However we create some pretty nasty looking code as well as a specific anti pattern called callback hell or pyramid of doom. In the next lessons we will examine some techniques for dealing with callback hell.

Contents