Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Callback Hell in Nodejs: A Solution With Fiber

DZone's Guide to

Callback Hell in Nodejs: A Solution With Fiber

Allow this article to be the Virgil to your Dante on the journey through callback hell, and learn how coroutines can help get you out of this situation.

· Web Dev Zone ·
Free Resource

Jumpstart your Angular applications with Indigo.Design, a unified platform for visual design, UX prototyping, code generation, and app development.

Apiumhub developers and any other developers that have worked with Node.js must have encountered a problem when dealing with the asynchronous APIs (I/O) that JavaScript offers; the famous JavaScript Callback. It’s the way JavaScript incorporates responding to events. In this article, I would like to talk about a solution with Fiber when dealing with Node.js Callback Hell. 

Callback Hell in Node.js: JavaScript Callback

A callback is a function, “A,” that is passed to another function, “B,” as a parameter. The function “B” executes the code “A” at some point. The invocation of “A” can be immediate, as in a synchronous callback, or, it can occur later as in an asynchronous callback. It’s actually a simple concept that can be well understood with an example:

var fs = require(‘fs’);

fs.readFile(‘test.json’, function(err, results) {   
    if (err) {       
        console.log(err);   
    }   
    console.log(JSON.parse(results).name);
});

In the code, we can see how to make a call to readFile and we pass it as a second parameter function (Callback Hell). In this case, readFile is an asynchronous operation and when it’s done with the operation of reading the file, it will execute the callback by passing the results of the operation to the parameters.

The use of callbacks makes the code difficult to write and maintain. It also increases the difficulty of identifying the flow of the application, which is an obstacle when it comes to debugging, hence the famous name for this problem: Callback Hell.

JavaScript Promises Hell 

A promise is the the future result of an asynchronous operation and is represented as a JavaScript object with a public interface. If we apply the code above, we would be left with the following code: 

var Promise = require(‘bluebird’);
var fs = require(‘fs’);

Promise.promisifyAll(fs);
 
fs.readFileAsync(‘test.json’)   .then(function(results) {   
    console.log(JSON.parse(results).name);   
})   .catch(function(err) {
    console.log(err);
});

While it is true that by using promises the code is more readable, we still end up having a problem; we have an application that is difficult to debug and maintain. Again, it is very easy to lose track of what is happening in the application, since we are talking about “future” results. Therefore, we will first have to convert all these APIs based on callbacks to Promises. That is when the coroutines (Fibers) are quite helpful. 

Solve Callback Hell: JavaScript Callback, Through a Coroutine 

Before coding, it is important to have a basic idea of what a coroutine is. A coroutine is a running line with its stack and local variables, but that shares global variables. It is very similar to a physical thread. The main difference between a physical thread and a coroutine is that, as far as the article is concerned, in the physical thread we can launch processes in parallel, whereas in coroutines, there are collaborative processes. This means that only one running process will be able to exist, and it’s that one that will decide to put itself in suspension in order to continue with the rest of the processes.

How to Apply Coroutines to Node.js

Now that we have seen the Node.js asynchronicity and what coroutines are, the only thing left is to link them. This is where the library wait.for comes into play.

This library, wait.for, abstracts and simplifies the use of node-fibers.

var wait = require(‘wait.for’);
var fs = require(‘fs’);

wait.launchFiber(function() {   
    try {       
        console.log(‘Start fiber’);       
        var results = wait.for(fs.readFile, ‘test.json’);       
        console.log(JSON.parse(results));   
    } catch (e) {       
        console.log(e);   
    }
});

console.log(‘Back in main’);

In this code, we can see how we launched a Fiber (coroutine) within our code, and, right after, we launch a console.log. The result of the code is the following:

Start fiber

Back in main

{ post: ‘NodeFibers’ }

The first piece that gets executed is the first console.log which is within the Fiber, which makes sense since it is the first instruction received. After that the readFile was executed, being an asynchronous operation, the Fiber (wait.for) is responsible for suspending the future pending response that will give us readFile and that will continue with the execution of the main thread, which is the console.log located outside the Fiber. Once that the readFile response is received, the Fiber will continue with the rest of the function.

Take a look at the Indigo.Design sample applications to learn more about how apps are created with design to code software.

Topics:
web dev ,node.js ,coroutines ,callback hell

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}