15. Node.js Lessons. Async Development. Introduction.


In real life you will barely witness a situation, when once a request has been received, the server can immediately respond it. To do so, the server generally needs some data. These data can come from a database or another source – for example, a file system. In our example, when using the fs module upon receiving a request at url ‘/’, the file index.html is being read and outputted to a visitor.

Pay your attention to the fact that fs is here just as an example; instead of this request we could have a database request or any other operation, which would need long stand-by time. In our case it is wait for the response from a disk:

If it were a request to a database, it would be wait for the response within the network from the base. Such code, from the one side, will work, but from the other, it has a scalability-related problem that will surely occur in practice being seriously used within the industry. For example, John followed this url ‘/’and requested the file fs.readFileSync(‘index.html’). John is waiting for a server response. The server is waiting when the file is read and is ready to send the data. At this moment Ilon, Linus and many others sign in, too, and wait for certain actions from the server, too. For example, they do not want this file, but something another – let’s say, a current date that can be obviously returned immediately.

But a server cannot do this because its interpreter JavaScript is busy at the moment – it is waiting for the disk response. Whenever this response is received, it will be able to continue the string, finish the request handling, and JavaScript will then be free and ready for some other requests.

As a result, we’ve got a situation, when one operation requiring a long stand-by period literally paralyzes the server’s functioning, which is unsatisfying, of course. Well, the request itself is quite normal, and such synchronized calls work seamlessly, if we need to create a console script, where we will read a file and then do something to it: write it somewhere and so on. It means, whenever we need to execute a sequence of tasks connected to the files, these calls/requests are handy, good and seamless. You will get some problems only within the server environment, when a number of things need to be conducted simultaneously. That’s why in this case you need to use another method included into the fs module that works asynchronously. In other words, the asynchronous method usually returns nothing immediately, but it initializes the file reading, receives a function argument that will receive this file when the process is over.

There is a following agreement related this function. If the reading result is successful, the function will be called with the first argument “null”, while the second argument will contain the file. But if an error occurs, the function will be called only with the first argument containing the information on it. So, we give a task to Node.js and execution continues. At this stage nothing is computed yet. It will be computed only here:

This kind of solution absolutely eliminates the problem of blocking as now JavaScript interpreter won’t wait for the file to be read. It will immediately continue execution and will be able to work with other visitors.

The function that Node.js must request upon completing the process is called a callback function. It means, the fs module returns JavaScript management to the interpreter and notifies it to start the work, while the module is finishing reading the file. Once the file is read, it will call back (callback).

One of the most serious hidden obstacles is that you can easily forget about any error possibility with the call of this kind. Let us see, what will happen, if the index.html file is lacking for some reason or there was some reading error – for example, a disk or rights error. In this situation, the fs module will do a callback with the first argument of an error object.

And there will be no second argument. If we do not handle an error, a visitor will get an empty string as a result. The worst thing is that your code will simply die without notifying you on an error. Moreover, you will barely know this information immediately, which means that you will hear visitor’s complaints prior to learning this fact. Second, it will be rather hard to debug it, i.e. find a cause. Respectively, to prevent it, you must handle an error argument. At least, if we are absolutely sure that an error will never happen, you can do the following:

But in this case it will be better to do this variant:

So, in the conclusion of this article, let us compare our synchronous and asynchronous codes by using the server implementation as an example. The synchronous variant is down below:

The synchronous variant is down below:

And here is the asynchronous one:

Let us start with the asynchronous variant. Synchronous requests of the readFileSync type are rarely used. They are used in those cases, when we can let ourselves block the JavaScript interpreter. In general, it means no parallelism. For example, a console script means – do A, B, C, etc. A synchronous call makes our interpreter do certain things, and it responds in “info.” If there was any mistake, it is rather an exception, and you can catch it using try catch:

An asynchronous variant works differently. Here is a different call, as you may see:

In order to get a result as an asynchronous code, we should use a callback function:

And you don’t have to wrap this request into try catch as it is pretty senseless. Well, you can do it, though, but on the other hand, there will be no error when using this call. This method works asynchronously and transmits any mistake to callback. Node.js has an agreement dealing with such practice: all built-in modules follow it, as well as we do: the first handler function argument is always an error. So, let us call this function as “сb.”

An error will call the following: cb(err), and if there is no error – cb(null, …). Respectively, a key difference between the synchronous and asynchronous variants here is that if we suddenly forget about try catch in the synchronous variant, we will definitely be notified about it. The exception will fall out and block the process in this code. In the asynchronous variant, if we forget to handle an error, it will malfunction. And we will receive no information about it. Respectively, it is vital to handle errors somehow choosing the asynchronous development. Of course, this kind is far more difficult, you need to create some callback functions, but still, there are certain ways to make the process easier, and we will talk about it later.

The lesson code is available here


The materials were borrowed from the following screencast

We are looking forward to meeting you on our website soshace.com

About the author

Stay Informed

It's important to keep up
with industry - subscribe!

Stay Informed

Looks good!
Please enter the correct name.
Please enter the correct email.
Looks good!

Related articles

How I Built an Admin Dashboard with Python Flask

In this article, I will share the how I built an admin dashboard. I will give a step by step guideline on how I built this application with Python ...

Getting started with Git Hooks using ghooks

Git hooks are configured scripts that are executed at specific moments during git operations. ghooks is a package that configures git hooks so that ...

React Native vs. Flutter: Which One Would Suit You Better?

Unveiling pros and cons of such cross-platform development frameworks as Flutter and React Native. Discover what suits you ...

No comments yet

Sign in

Forgot password?

Or use a social network account


By Signing In \ Signing Up, you agree to our privacy policy

Password recovery

You can also try to

Or use a social network account


By Signing In \ Signing Up, you agree to our privacy policy