> Manuales > Manual de NodeJS

Para definir Node.JS mejor viene bien observar algunas características de la plataforma y las diferencias de NodeJS con Javascript común y con otros lenguajes de programación.

Este Manual de Node.JS está creado a través de unas charlas #nodeIO que hemos realizado en DesarrolloWeb.com, de las cuales estos artículos son una transcripción. En este punto estamos todavía en la primera charla, en la que Alejandro Morales nos está aclarando algunos conceptos importantes para poder entender bien qué es NodeJS.

En el artículo anterior vimos cómo se instalaba esta NodeJS y en el presente texto veremos en detalle algunas de las características más fundamentales de NodeJS. Entre todas ellas nuestro ponente Alejandro Morales destacó: JavaScript sin limitaciones, Programación asíncrona y Programación orientada a eventos. Todos estos puntos los veremos a continuación.

Un Javascript "sin restricciones"

Con NodeJS tenemos un "Javascript sin restricciones", tal como afirma @_alejandromg, ya que todo se ejecuta en el servidor y no tenemos que preocuparnos de si nuestro código será compatible o no con distintos clientes. Todo lo que escribas en Node JS y te funcione en tu servidor, estarás seguro que funcionará bien, sea cual sea el sistema que se conecte, porque toda la ejecución de código del servidor se queda aislada en el servidor.

Nota: Este detalle de fiabilidad y compatibilidad, o lo que ha llamado el autor como Javascript "sin restricciones" (por estar ejecutado en un ambiente seguro, del lado del servidor) no deja de ser una ventaja de todos los lenguajes del lado del servidor, como PHP, ASP.NET, JSP, etc.

Pero no sólo eso, el Javascript original tiene algunas estructuras de control que realmente no se utilizan en el día a día, pero que realmente existen y están disponibles en NodeJS. En algunas ocasiones resulta especialmente útil alguna de las mejoras de Javascript en temas como la herencia.

Otro ejemplo es que en Javascript haces:

for(var key in obj){ }

Mientras que en las nuevas versiones de Javascript podrías hacer esto otro:

Object.keys(obj).forEach()

Programación Asíncrona

Éste es un concepto que algunas personas no consiguen entender a la primera y que ahora toma especial importancia, dado que NodeJS fue pensado desde el primer momento para potenciar los beneficios de la programación asíncrona.

Imaginemos que un programa tiene un fragmento de código que tarda cinco segundos en resolverse. En la mayoría de los lenguajes de programación precedentes, durante todo ese tiempo el hilo de ejecución se encuentra ocupado, esperando a que pasen esos cinco segundos, o los que sea, antes de continuar con las siguientes instrucciones. En la programación asíncrona eres capaz de liberar el proceso de modo que los recursos se quedan disponibles para hacer otras cosas durante el tiempo de espera.

Un ejemplo claro de esto es una llamada a un servicio web, o una consulta a la base de datos. Una vez realizada la solicitud generalmente pasará un tiempo hasta que se obtenga la respuesta. Ese tiempo, por corto que sea, dejaría un proceso esperando en la programación tradicional y en la asíncrona simplemente se libera. En NodeJS, o en Javascript en general, cuando esa espera ha terminado y se ha recibido la respuesta, se retomará la ejecución del código. Para definir las acciones a realizar (código a ejecutar) cuando se haya terminado esa espera, se especifica el código mediante funciones llamadas habitualmente "callbacks". Esas funciones contendrán las líneas de código que ejecutar al final de esos procesos de espera, y una vez se ha recibido la respuesta.

La filosofía detrás de Node.JS es hacer programas que no bloqueen la línea de ejecución de código con respecto a entradas y salidas, de modo que los ciclos de procesamiento se queden disponibles durante la espera. Por eso todas las APIs de NodeJS usan callbacks de manera intensiva para definir las acciones a ejecutar después de cada operación I/O, que se procesan cuando las entradas o salidas se han completado.

Nota: Estos callbacks probablemente ya los hayas usado un montón de veces si tienes experiencia con Javascript del lado del cliente, porque se usan en funciones muy habituales como setTimeout(), que también está disponible en NodeJS. Librerías Javascript como jQuery también las usan de manera intensiva.

Por ejemplo miremos este código:

console.log("hola");
fs.readFile("x.txt", function(error, archivo){
   console.log("archivo");
})
console.log("ya!");

Realmente Javascript es primeramente síncrono y ejecuta las líneas de código una detrás de otra. Por ese motivo, como resultado de ejecución del código anterior, primero veremos el mensaje "hola" en la consola, luego el mensaje "ya!" y por último, cuando el fichero terminó su lectura, veremos el mensaje "archivo".

Por la forma de ejecutarse el código se puede entender la programación asíncrona. La segunda instrucción (que hace la lectura del archivo) tarda un rato en ejecutarse y en ella indicamos además una función con un console.log ("archivo"), esa es la función callback que se ejecutará solamente cuando termine la lectura del archivo. Por ese detalle, lo último que aparecerá en pantalla es el contenido del fichero. Este detalle es de extrema importancia para entender la programación con NodeJS.

Problema del código piramidal

El uso intensivo de callbacks en la programación asíncrona produce el poco deseable efecto de código piramidal, también conocido habitualmente como "código Espagueti" o "callback hell". Al utilizarse los callbacks, se meten unas funciones dentro de otras y se va entrando en niveles de profundidad que hacen un código menos sencillo de entender visualmente y, por tanto de mantener durante la vida de las aplicaciones.

La solución es hacer un esfuerzo adicional por estructurar nuestro código. Básicamente se trata de modularizar el código, escribiendo cada función aparte e indicando solamente su nombre cuando se define el callback. Podrías incluso definir las funciones en archivos aparte y requiriéndolas con require("./ruta/al/archivo") en el código de tu aplicación. Todo esto lo veremos con detalle en numerosos ejemplos en el Manual de NodeJS, por lo que no te debes de preocupar mucho si todavía no lo entiendes.

Al conseguir niveles de indentación menos profundos estamos ordenando el código, con lo que será más sencillo de entender y también más fácil de encontrar posibles errores. Además, a la larga conseguirás que sea más escalable y puedas extenderlo en el futuro o mantenerlo por cualquier cuestión.

Nota: También en ES6 existen otras herramientas como las promesas que te ayudan a mantener tu código ordenado con la programación asíncrona y el uso de callbacks

Algunos consejos a la hora de escribir código para que éste sea de mayor calidad:

Programación orientada a eventos (POE)

Conocemos la programación orientada a eventos porque la hemos utilizado en Javascript para escribir aplicaciones del lado del cliente. Estamos acostumbrados al sistema, que en NodeJS es algo distinto, aunque sigue el mismo concepto.

En Javascript del lado del cliente tenemos objetos como "window" o "document" pero en Node.JS no existen, pues estamos en el lado del servidor.

Eventos que podremos captar en el servidor serán diferentes, como "uncaughtError", que se produce cuando se encuentra un error por el cual un proceso ya no pueda continuar. El evento "data" es cuando vienen datos por un stream. El evento "request" sobre un servidor también se puede detectar y ejecutar cosas cuando se produzca ese evento.

Volvemos a insistir, NodeJS sería un equivalente a PHP, JSP, ASP.NET y entonces todo lo que sean eventos de Node, serán cosas que ocurran en el lado del servidor, en diferencia con los eventos de Javascript común que son del lado del cliente y ocurren en el navegador.

Nota: La comparación de Node.JS con lenguajes del lado del servidor viene bien para entender cómo pueden sus eventos ser distintos que los de Javascript del lado del cliente. Sin embargo debemos saber que que Node.JS es más bien una plataforma basada en Javascript. NodeJS viene con muchas utilidades para programación de propósito general y para realizar programas que implementarían servidores en sí mismos, por lo que su equivalente más próximo podría ser algo como Django o Ruby on Rails. Aunque habría que matizar que esa comparación puede ser un poco atrevida, debido que NodeJS estaría en un nivel mucho más bajo (más cercano a la máquina) y aunque lo podrías usar sin más añadidos para el desarrollo de sitios web, se combina con otros frameworks como ExpressJS para dar mayores facilidades para la creación de sitios aplicaciones web.

Conclusión

Poco a poco vamos entendiendo qué es (y que NO es) NodeJS. Son todo conceptos que resultarán nuevos para muchos de los lectores y por ello era importante dejarlos claros. Ahora vamos a pasar a explicar algunas otras cosas de interés que utilizamos en el día a día en esta plataforma, como el gestor de paquetes npm.

Miguel Angel Alvarez

Fundador de DesarrolloWeb.com y la plataforma de formación online EscuelaIT. Com...

Manual