Callback Hell NodeJs: a solution with Fiber

Share This Post

Apiumhub developers and any developer that has worked with Node.js must has encountered a problem when dealing with 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 in Node Js Callback Hell.

Callback Hell 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 will 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 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 making debug, hence the famous name to 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.

  Why use the NestJS framework?

Solve Callback hell – JavaScript Callback, through a coroutine

Before entering in coding, it is important to have a basic idea of what is a coroutine. 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 NodeJS ?

Now that we have seen the NodeJS asynchrony and what coroutines are, the only thing left is to link them. This is where the library wait.for comes

(https://github.com/luciotato/waitfor) which abstracts and simplifies the use of node-fibers

(https://github.com/laverdet/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 that was 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.

  Liquibase on Kubernetes

If you are interested in software development best practices, I recommend you to subscribe to our monthly newsletter to receive latest tips.

If you found this article about Callback hell interesting, you might like…

F-bound over a generic type in Scala

Scala Generics: Scala Type bounds

Tmux cheat sheat

SRP in object oriented design

Microservices vs Monolithic architecture

“Almost-infinit” scalability

Author

Leave a Reply

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

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

Subscribe To Our Newsletter

Get updates from our latest tech findings

Have a challenging project?

We Can Work On It Together

apiumhub software development projects barcelona
Secured By miniOrange