Todos los desarrolladores que hayan trabajado con NodeJS se habrán encontrado con un problema a la hora de tratar con las APIs asíncronas (I/O) que JavaScript ofrece, los famosos Callback. Es la manera que incorpora JavaScript de responder a eventos. En este articulos vamos a ver como usar Fibers en Nodejs. 

 

Callback Hell ? Fibers en Nodejs! 

 

Un Callback es una función “A” que se pasa a otra función “B” como parámetro. La función “B” ejecutará el código de “A” en algún momento. La invocación de “A” puede ser inmediata, como ocurre en un Callback síncrono, o puede ocurrir más adelante, en el caso de un Callback asíncrono. Es un concepto simple, que con un ejemplo se entenderá perfectamente:

 

 

var fs = require('fs');

fs.readFile('test.json', function(err, results) {
 if(err) {
 console.log(err);
 }

console.log(JSON.parse(results).name);
 });

 

En el código se ve cómo hacemos una llamada a readFile y le pasamos como segundo parámetro una función (callback). En este caso, readFile es una operación asíncrona y cuando acabe con la operación de leer el fichero, ejecutará el callback pasándole como parámetros los resultados de la operación.

El uso de callbacks hace que el código sea difícil de escribir y de mantener. También incrementa la dificultad de identificación del flujo de la aplicación, lo cual es un obstáculo a la hora de hacer debug, de ahí el famoso nombre a este problema: Callback Hell.

 

Promises hell

 

Una promesa representa el futuro resultado de una operación asincrónica y es representada como un objeto de javascript con una interfaz pública. Si aplicamos promises al código anterior nos quedaría el siguiente código:

 

 

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);
 });

 

Si bien es cierto que usando promises el código queda algo más legible, seguimos teniendo el problema de que, como resultado, tenemos una aplicación difícil de debugar y mantener. De nuevo, es muy fácil perder el hilo de lo que está pasando en la aplicación, ya que estamos hablando de “futuros” resultados. Por tanto, previamente tendremos que convertir todas esas APIs basadas en callbacks a Promises. Es en este punto donde nos ayudan las coroutines (Fibers)

 

Fibers (Coroutines)

Antes de entrar en código está bien tener una idea básica de lo que es una coroutine. Una coroutine es una línea de ejecución con su stack y sus variables locales, pero compartiendo variables globales. Es muy similar a un thread físico. La principal diferencia entre un thread físico y una coroutine es que (en lo que al artículo concierne) en el thread físico se pueden lanzar procesos en paralelo, mientras que en las coroutines son procesos colaborativos. Esto quiere decir que sólo va a poder existir un proceso en ejecución, y será éste el que decidirá ponerse en suspensión para poder continuar con el resto de procesos.

 

Cómo aplicar coroutines a NodeJS?

Ahora que ya hemos visto cómo trata la asincronía NodeJS y que son las coroutines, solo nos queda enlazarlos. Aquí es donde entra la librería wait.for  la cual abstrae y simplifica el uso de 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');

 

En este código podemos ver como lanzamos una Fiber (coroutine) dentro de nuestro código y justo después lanzamos un console.log, el resultado del código es el siguiente:

 

 

Start fiber
 Back in main
 { post: 'NodeFibers' }

 

Lo primero que se ha ejecutado es el primer console.log que está dentro del Fiber, algo lógico ya que es la primera instrucción que recibe, luego se ha ejecutado el readFile lo que al ser una operación asíncrona, la Fiber (wait.for) se encarga de suspenderse a la espera de la futura respuesta que nos dará readFile y seguirá con la ejecución del main thread, que es el console.log situado fuera del Fiber, una vez recibida la respuesta del readFile, la Fiber continuará con el resto de la función.

 

Si te gustó el articulo sobre Fibers en NodeJS, te puede interesar: 

 

Principio de responsabilidad única 

Por qué Kotlin?

Patrón MVP en iOS

F-bound en Scala

Sobre Dioses y procrastinación

Arquitectura de microservicios

Simular respuestas del servidor con Nodejs

 

Suscríbete a nuestro newsletter para estar al día de los eventos, meet ups y demás artículos!