The web is quickly becoming the preferred platform for software development and with user traffic higher than it's ever been, it's become incredibly important to build applications that can scale and handle hundreds, if not thousands of users using the application concurrently. As a result, newer applications are being developed with asynchrony in mind, but what is asynchrony? Asynchrony Explained In traditional computing, tasks are executed in the order in which they appear in a program. This procedural style of computing is how most systems software and many types of application software work under the hood. Procedural programming follows the basic logical steps of computing (if condition is true, run this process, else run this other process). This process is known as control flow and will often run until a program it's finished executing. This model of computing is fairly one dimensional and introduces a serious issue: blocking. Blocking occurs when a particular task prevents subsequent tasks from running. Traditionally, this is how most programs are built. In reality, computers today are so incredibly fast that blocking is not often an issue, but when we move into web development blocking becomes a much bigger problem. Being able to write non-blocking programs is especially important to ensure a positive user experience. When you submit a Facebook status, Facebook submits this data through an AJAX request instead of a typical HTTP request. This allows the process to run in the background so you, as the user, can continue to use the site even if the request/response cycle hasn't completed. Non-blocking, asynchronous programming is JavaScript's main value proposition and has helped popularize the Node.js server-side runtime environment. Because JavaScript is an event-driven language, you can use callback functions to load chunks of data as they're being processed instead of waiting until an entire file has finished processing. I know I just dropped a bit of vocabulary on you, but don't worry, it will be explained. First, a quick explanation of callback functions, then let's write some code! What is a Callback Function? A callback function is, essentially, an anonymous function that can be called within another function. You may have seen this in jQuery: In this function, you're calling the click event listener when someone clicks on a button with a btn_1 ID. That event listener fires off that second function, which displays the alert in the body. That second function is a callback function and is called as a parameter of the click function. Hopefully this is making some sense. Callback functions are allowed in JavaScript because functions are treated as first-class objects - like strings, integers, arrays, etc. - and can be called within a function like any other object. Callback functions are incredibly useful because they allow for a process to run in the background while the rest of the program continues. In the jQuery above, storing that 'alert' in a callback function allows it to be called outside of the flow of the application and won't block other processes from running. Callback functions are so named because we trust that when the the outer function is done processing its input (aka a file or a DOM element), the callback function will be, well, called on to finish the job. Our Program Our program is a very simple script that grabs a file, uploads it, and prints its contents to the console. In a vacuum, the program works fine, however, our manager wants to incorporate this script into the main codebase. This presents a major issue: we will be reading from a very large filesystem and we need to be able to do this without blocking other processes in the larger program from running. Time to update the code! Let's look at our original script: To quickly break this down, we're first requiring the http and fs modules. We then call the readFileSync function to grab the contents in the '/etc/hosts' directory, upload its contents, and throw them into a variable called contents. Once that process finishes we log the contents of contents to the console and then tell the user when it's complete. Looks good right? Well by traditional programming standards, we completed this task in a canonical, procedural fashion. However, we now need to convert it to an asynchronous operation so that it runs at scale. Converting our Code We are going to rewrite our code so that this process can run in the background while the rest of the program continues. In order to do this, we'll implement a callback function. This callback function will print the contents of the file to the console and will be automatically triggered when the file is done uploading. However, since the callback function is defined within the scope of the larger readFile function, it won't get in the way of other functions that are running. Here's our updated code: There we go! Now, the readFile function will execute and even if the subroutine defined within that process is still running, we can still continue on with the rest of the program. The callback function, which prints the contents to the console, will fire off when the file is done uploading, but because it's defined within the readFile function instead of after it, it will not prevent subsequent processes from running. You may have also noticed that the first parameter of the callback function was 'err'. This is simply considered good practice when writing asynchronous JavaScript. This will allow you to catch errors and will come in handy when writing AJAX requests. Conclusion Asynchronous programming and callback functions can seem like esoteric concepts, but they are the driving force behind Node.js and concurrency in JavaScript. You will often hear people complain about 'callback hell' and, yes, it is true that there are other languages that handle concurrency in a much cleaner way, but the benefits of using Node.js and callback functions is that they are paradigms with which most web devs are familiar. Anyway, give it a go and see how much of your code you can refactor to be more asynchronous and more performant!
Comments (1)
Yuvraj Singh
on 10/24/2024Keep up the good work