Usando Atom para Node.js

Node es una plataforma que me gusta para hacer pruebas de concepto, porque con poco código es fácil hacer muchas cosas.

Buscando un editor he empezado a utilizar Atom. Viniendo como vengo de Java, estoy familiarizado con entornos como Eclipse o IDEA de JetBrains, pero me apetecía practicar con algo mas ligero. Vim es otro editor que manejo bien y me gusta, pero no lo veo para esto. Me encanta para editar rápidamente sobre la línea de comando, pero no para desarrollar de forma continua.

Atom es sencillo, es bonito, es abierto, y tiene una comunidad muy rica detrás. No es tan rápido como Sublime y Visual Studio Code, pero me da igual.

En un sistema Linux como Ubuntu la instalación es la habitual con su gestor de paquetes. En la sección Atom Basics del manual de Atom se describen los comandos básicos para desenvolverse en el editor, en caso de duda un “Ctrl+Shift+P” te permite encontrar lo que necesites.

Una de las características de Atom es que es muy personalizable, existe multitud de extensiones disponibles para adaptarlo a tus necesidades. La instalación de estos paquetes se puede hacer con un “apm install <nombre-de-paquete>“.

Las que siguen son las extensiones que he encontrado mas útiles para desarrollar programas en servidor. He ignorado las que tienen que ver con la parte de presentación como autoclose-html, pigment o color-picker.

Las primeras en mi lista son atom-ternjs, node-debugger y script. Para mí son las mas necesarias, y las primeras que he instalado.

atom-ternjs

  • Acostumbrado a trabajar en IDEs como Eclipse algo que busco de forma natural es una utilidad de autocompletado de código y de chequeo de sintaxis. Esto es lo que encuentras en esta extensión. Como indica su documentación, si quieres usarla en tu proyecto, debes añadirle un fichero de configuración para tern donde le puedes indicar como quieres que te ayude.

node-debugger

  • Esta extensión es un depurador para Node con las funciones habituales de inserción de puntos de ruptura, ejecución paso a paso y consulta de pila de llamadas, entre otras.

script

  • Esto es una pequeña maravilla que te permite seleccionar un trozo de código y ejecutarlo en un momento. Algo como https://repl.it/ pero dentro de Atom. Ideal para prototipar una función o para probar con rapidez.

Otro grupo de extensiones que uso son las que me ayudan a editar mas rápidamente, porque visualizo mejor las cosas, o porque llego a ellas mas rápidamente: minimap, open-recent, highlight-selected, file-icons, maximize-panes, fold-lines y tool-bar.

minimap

  • Muestra a la derecha del editor una visión resumida de todo el código contenido en el fichero, permitiendo situarte con mas facilidad. Existen extensiones relacionadas con esta que permiten indicar la posición del cursor en el minimapa.

open-recent

  • En el menú de fichero muestra siempre los ficheros y carpetas que hemos abierto mas recientemente.

highlight-selected y minimap-highlight-selected

  • Al seleccionar una variable o una palabra clave, todas las ocurrencias de las mismas en el fichero aparecen resaltadas.

file-icons

  • Asocia un icono para cada extensión de fichero facilitando encontrar lo que buscas.

maximize-panes

  • Permite maximizar el panel del editor donde estás trabajando sin cerrar el resto de paneles.

fold-lines

  • Permite compactar en una línea distintos bloques de código para facilitar la lectura.

tool-bar

  • Aunque me encanta usar atajos de teclado, mi magia es limitada y necesito de una barra de herramientas como esta. Permite personalizar su contenido.

Y ahora este grupo final de plugins que veo interesantes. Puedo vivir sin ellos pero les he dado una oportunidad: linter, auto-detect-indentation y atom-beautify.

linter y linter-eslint

  • Es una extensión para corrección de código que también se integra en otros entornos de desarrollo. linter es el paquete base que soporta HTML, CSS y JavaScript. linter-eslint es una ampliación sobre el anterior específico para JavaScript y JSX. Como en el caso de tern, para usarlo en tu proyecto debes incluir un fichero de configuración eslint donde puedes detallar, por ejemplo, si se va a programar en JavaScript ES6 o con una versión anterior.

auto-detect-indentation y atom-beautify

  • El primero configura la identación del fichero basado en el contenido que ya tiene, no solo en las settings del editor. El segundo organiza el código para verlo mejor.

Y tras tanta personalización, ¿que pasa si quieres llevártela a otra máquina, quieres compartirla, o simplemente no perderla? Pues usar otra extensión: sync-settings.

syn-settings

  • Permite guardar la personalización realizada en el editor en un gist de GitHub. Hay que tener una cuenta disponible. Para hacer el backup hay que introducir en Atom el token de acceso a GitHub y el ID del gist donde vas a hacerlo. Aquí puedes encontrar la configuración descrita en este post.

En Internet hay muchas páginas mostrando conjuntos de extensiones preferidas para distintos usos. Aquí he compartido las mías.

Node.js y el Event Loop

Una de las razones que ha hecho popular a Node.js es su extraordinaria velocidad de respuesta en comparación con un servidor Java (por ej. Tomcat). Obviamente esto no se consigue gratis, y es que a diferencia de un servidor Java, Node.js es “single threaded” solo hay un hilo de ejecución atendiendo todas las peticiones, no se levanta uno nuevo cada vez. Esto elimina toda la sobrecarga de gestión de los hilos (locks y demás).

Pero para que esto funcione las aplicaciones tienen que ser programadas de forma que no se bloqueen en tareas lentas como una consulta a la red, un acceso base de datos o a un fichero. Es por ello que la programación asíncrona está en el fundamento de Node.js. Node.js es una apuesta a que un solo hilo con procesado asíncrono tiene mejor rendimiento y escalabilidad que una implementación multi-hilo.

Programación síncrona

Node.js se apoya en un motor de ejecución javascript como el que contiene cualquier navegador. Este motor es el que es single-threaded, y en el navegador es la razón de que si tienes una página y tu código realiza varias llamadas de red síncronas que tardan mucho, acabes con una página que se queda bloqueada y donde no puedes hacer click en ningún sitio.

Es el mismo problema que tenemos en Node.js si hiciéramos muchas llamadas síncronas costosas (base de datos, ficheros, red). No habría respuesta hasta finalizadas todas las tareas.bloqueos_node

La forma de evitar los bloqueos es con programación asíncrona y en un navegador como Chrome esto es posible porque aparte del hilo de ejecución del motor javascript hay otros hilos de gestión. Entre ellos el famoso Event Loop. ¿Cómo funciona?

Programación asíncrona y el Event Loop

Cuando se ejecuta un código javascript en una página, de forma síncrona, usa la pila de llamadas del motor. Los métodos invocados se van apilando y desapilando y solo se devuelve el control al navegador cuando la pila se vacía. En este modo síncrono, si hay tareas que tardan mucho, podemos vernos con que la página se “congela” durante un buen rato.

callstack_sincrono

Si realizamos tareas de forma asíncrona, como cuando invocamos el API setTimeOut pasando una función de callback y un retardo, esta es ejecutada por un hilo independiente del navegador, fuera de la pila de Javascript. Cuando termina de ejecutarse la función de callback queda en una cola, a la espera de poder ejecutarse.

callstack_asincrono

¿Cuando se ejecuta la función de callback? En cuanto la pila se libera otro hilo de gestión del navegador, el famoso Event Loop, coge la función para meterla en la pila.

Por todo lo anterior es que se usa ese truco de llamar a funciones pasándolas a setTimeOut con delay 0. Las funciones no se ejecutan directamente, sino que acaban en una cola, y el loop irá pasándolas a la pila cada vez que se vacíe. En esos huecos en medio la página responde a nuestras acciones, no está bloqueada. Provocamos asincronía y creamos páginas mas dinámicas.

APIs asíncronas como setTimeOut hay muchas: para llamadas en red, consulta de almacenes de datos, etc.

Node.js resuelve la programación asíncrona como hemos descrito antes para el navegador. Y es que Node.js usa el motor javascript en que se basa Chome, y los procesos de gestión alrededor del motor son como los que usa el navegador.

chromeVer también: