code

How to survive from Node.js and JavaScript callbacks

Many people coming from Java ecosystem to Node.js (like I did) are facing problems to adjust with the new platform philosophy since the basic principles of JavaScript itself are way different from the other well-known Object Oriented Languages.

Personally I think the biggest problem that I had was to understand the nature of functions in JavaScript and subsequently the way callbacks behave.

The truth is the first time I read about them I thought that I understood them. Unfortunately understanding them was not enough because all those years of experience turned into a barrier for me.

I will try to present the conceptual problem that I had in the beginning and also what I did in order to overcome it.

THE PROBLEM

Let’s say that you want to make a simple program that does 3 steps.

Step1. It reads a file.

Step 2. It accepts a prompt from console with username and password.

Step 3. It sends an email connecting to the mail server using the given credentials and having as a body the file contents read from step 1.

Normally with a conventional OO language you would create 3 functions each one doing one step and call them all three from the body of a third with the order 1, 2, 3.

Most programming languages are doing things synchronously by default which means that step 2 will be executed after 1 and 3 after 2.

This is a sample of something we could do in Java. For the sake of the example please ignore the static and the lack of OO architecture.

public static void main(String[] args) {
readfile();
getCredentials();
sendMail();
}

public static void readfile(){}

public static void getCredentials(){}

public static void sendMail(){}

Unfortunately (and fortunately) the following work flow would not work in Node.js. When your code reaches the step 2 the result of step 1 will not be ready and on step 3 the result of step 2 will not be ready either. The reason is that most modules of node.js work asynchronously and that requires a more delicate approach.

THE SOLUTION

As a matter of fact there are 3 solutions.

A) Using callbacks properly

B) Using nested callbacks

C) Using Promises.

I will skip solution B and C because B is not a decent solution since the readability of the code would be terrible and C because it is a different topic.

I will try to focus on solution (A).

As we saw on the previous code we had 3 functions doing the work and one more calling those 3 with a sequence.

In Node.js you will only need the fourth function to trigger the Step 1 and passing as a parameter the function that knows what to do after Step 1 ends.

Note that the fourth function – let’s call it trigger function – will not do anything more than calling step 1. The callback function 1 will be responsible to acquire the result of step 1 and trigger step 2 passing a new callback to step 2. Call back function 2 will be called by step 2 after finishing and that will call step 3.

Here is a diagram showing the procedure:

Here is some ample code:

function trigger(){
readfile(callBack1);
}

function callBack1(){
getCredentials(callBack2);
}

function callBack2(){
sendMail();
}

// Step 1

function readfile(nextStep) {
fs.readfile(path, function (error, text) {
nextStep();
});
}

// Step 2

function getCredentials(nextStep) {
prompt.getCredentials(value, function (error, result) {
nextStep();
});
}

// Step 3

function sendMail() {
transporter.sendMail(mailOptions, function (error, info) {
//done
});
}

Leave a Reply

Your email address will not be published. Required fields are marked *