Seleccionar página
Como comentamos en un artículo anterior, los sistemas RPC son extremadamente flexibles y permiten llamar a funciones remotas de forma prácticamente transparente, pudiendo centrar nuestros esfuerzos de desarrollo en la funcionalidad y no en los mecanismos de comunicación entre las distintas partes de nuestra aplicación.

Hemos creado una aplicación de ejemplo para poder comprender mejor cómo podemos utilizar la librería jsRPC para gestionar de forma muy sencilla las llamadas a procedimientos remotos de forma transparente. En esta aplicación hemos utilizado el modelo RPC para que el navegador invoque funciones del servidor y para que los diferentes microservicios invoquen de forma remota funciones entre ellos.

El código fuente completo de este ejemplo lo puedes obtener en:

https://github.com/todojs/jsrpc-example

Es un proyecto con un cliente HTML + JS Vanilla (se puede usar cualquier framework front como React, Angular o Vue, pero hemos querido no distraer de la implementación) y un servidor en NodeJS con NeDB como sustituto a la base de datos (se podría haber usado MongoDB o una base de datos SQL).

Core

En primer lugar, hemos creado tres objetos: courses, teachers y students. Como es fácil adivinar, es una micro aplicación de ejemplo para la gestión de cursos. Cada uno de estos objetos tiene los siguientes de métodos que realizan las operaciones que necesitamos en nuestra aplicación:

  • .list([query][, sort]) obtiene todos los registros en base a una query (por defecto devuelve todos) y un criterio de ordenación (por defecto se ordena por nombre).
  • .get(id) obtiene los datos detallados de un registro.
  • .add(data) crea un nuevo registro.
  • .edit(id, data) actualiza los valores de un registro.
  • .del(id) elimina un registro.

Todos estos métodos devuelven una promesa. Si tenéis curiosidad por cómo están implementados en detalle estos métodos, podéis ver su código fuente en:

microservicios/courses/coures.js
microservicios/teachers/teachers.js
microservicios/students/students.js

Estos servicios se han probado con una serie de tests que también están incluidos en el repo y que por medio de Mocha y Chai van llamando a cada uno de los métodos comprobando diferentes combinaciones y casos.

Sub y Skeleton

La idea es que estos métodos se utilicen como llamadas locales (dentro del mismo espacio de direcciones, es decir, dentro del mismo programa) o como llamadas remotas (RPC) sin que tengamos que cambiar nada. Es decir, que si quiero obtener una lista con todos los alumnos (tanto remotamente como localmente) sólo tendré que llamar a:

students.list().then(function(data) {
  // …
});

Para ello vamos a hacer uso de las funciones de jsRPC para crear el programa stub que utilizaremos en el cliente y el programa skeleton que usaremos en el servidor. Antes de esto tenemos que instalar la librería con:

npm install @todojs/jsrpc –save

En nuestro repo, al tenerlo ya incluido en las dependencias, basta con:

npm install

Para cada uno de los objetos se ha creado su programa squeleton, que se ejecutará en la parte remota, con la función skeletonify() de la siguiente forma:

const courses     = require ('./courses');
const skeletonify = require ('@todojs/jsrpc/skeletonify');
module.exports    = skeletonify ('courses', courses);

De igual forma, para cada uno de los objetos se ha creado su programa stub, que se ejecutará en la parte local, con la función stubify() de la siguiente forma:

(root => {
  const stubify = typeof window !== 'undefined' ? window.stubify : require ('@todojs/jsrpc/stubify');
  const courses = stubify ("http://localhost:9001", 'courses');

  if (typeof module !== 'undefined' && module.exports) {
    module.exports = courses
  } else {
    root.courses = courses;
  }
}) (this);

El código de los stub está preparado para ser utilizado desde un navegador y desde un programa Node de forma indistinta, de esta forma podremos llamar remotamente a estas funciones desde cualquier sitio que las necesitemos.

Estructura de ficheros

Cada objeto de nuestra aplicación tiene ahora tres ficheros, uno con su código: courses.js, otro con su programa skeleton: courses-squeleton.js y otro con su programa stub: coures-stub.js, y podemos distribuirlos según nuestras necesidades.

En muchas ocasiones el fichero con el stub tiene el mismo nombre que el fichero con los métodos originales, lo cual simplifica la sustitución de uno por otro, ya que no cambian el nombre del módulo. En nuestro caso los hemos dejado con nombres diferentes sólo con fines didácticos.

Desde el navegador vamos a querer llamar de forma remota a los tres objetos courses, teachers y students, por lo que hemos incluido sus stub dentro de la carpeta front, que incluye todo lo que vamos a servir al cliente. Como estos programas hacen uso de stubify() también hemos movido aquí esta función desde la carpeta node_modules, aunque también podríamos haber hecho una referencia para evitar realizar esta copia del fichero.

En el servidor hemos organizado la ejecución en tres microservicios, uno por cada uno de los objetos. Para simplificar el funcionamiento lo hemos preparado para que cada uno arranque en un puerto diferente:

  • courses: puerto 9001
  • teachers: puerto 9002
  • teachers: puerto 9003

Cómo los métodos del objeto courses llaman a su vez a métodos de los objetos teachers y students, y como estos se van a ejecutar en otro microservicio, hemos incluido los stub de estos objetos dentro de la carpeta del microservicio courses. Cada uno de los microservicios tiene su propia carpeta con los datos que maneja, no accediendo directamente nunca unos a los datos de los otros.

En cada microservicio también hay un fichero index.js que simplemente configura el puerto y llama al programa skeleton de cada uno de ellos:

process.env.port = process.env.port || 9001;
require ('./courses-skeleton');

Ejecutar el ejemplo

Ya lo tenemos todo preparado, por lo que podemos empezar a arrancar cada uno de nuestros microservicios con:

cd microservices/courses
node index.js
cd microservices/teachers
node index.js
cd microservices/students
node index.js

Ahora arrancamos el servidor http para que nos sirva la página de ejemplo:

./node_modules/.bin/http-server ./front -o

Si todo ha funcionado correctamente, se abrirá un navegador y podremos ir consultando las diferentes pantallas:

Llamadas entre los elementos

Para comprender un poco mejor cómo funciona, vamos a analizar cómo consultamos un detalle de un curso en el navegador. Para obtener todos los cursos se está haciendo una llamada de este tipo:

courses.get (id)
  .then (function (result) {
    //...
  })
  .catch (function (err) {
    error (err.message);
  });

Este método courses.get() se ejecuta en el servidor a través del sistema jsRPC, y este a su vez llama a métodos de students y de teachers:

  const currrentTeachers = await teachers.list ({_id : {$in : data.teachers}});
  // ...
  const currrentStudents = await students.list ({_id : {$in : data.students}});

Tal y como lo hemos configurado, estas llamadas son enviadas a los microservicios correspondientes que ejecutan remotamente las funciones que les hemos solicitado.

Ejecutar estos métodos local o remotamente sólo cambia si estamos invocando al módulo directamente o a su sustituto el stub, que es quien ser encarga de gestionar la llamada remota, por lo que nuestro código no se ve afectado por este cambio.

Conclusión

De esta forma podemos gestionar todas las comunicaciones entre las diferentes piezas de nuestro sistema de forma absolutamente transparente. Esta es la gran ventaja de las soluciones RPC, que nos permiten centrarnos en la funcionalidad de nuestro código y gestionan por nosotros todas las características internas de la comunicación entre los diferentes procesos.

Os invitamos a explorar este ejemplo y descrubir por vosotros mismos las capacidades que tiene el sistema jsRPC en concreto y las soluciones RPC en general.

Novedades

Web Components: pasado, presente y futuro

Web Components: pasado, presente y futuro

Los Web Components aparecieron en el panorama de desarrollo hace ya bastante tiempo. Desde su presentación se les ha prestado mucha atención, pero lo cierto es que no han sido acogidos de forma generalizada, quizás por la difusión de nuevos y potentes frameworks. Nos preguntamos qué ha pasado con este estándar y, sobre todo, que puede pasar de aquí en adelante con el uso práctico de los componentes web.

Adaptar un componente web para Microsoft Edge

Adaptar un componente web para Microsoft Edge

Si quieres que tus componentes web funcionen sin problemas en Microsoft Edge, es conveniente que conozcas algunas de sus carencias y cómo resolverlas. Edge tiene soporte nativo a algunas de las características clave de los web component, pero hay que utilizar polyfill en otras y hay que tener en cuenta algunas limitaciones. Próximamente Edge utilizará Chromium como base de su desarrollo, pero de momento, es necesario aplicar estas soluciones.

12 pasos para construir un componente web

12 pasos para construir un componente web

Para conocer cómo se desarrolla realmente un componente web no puedes perderte esta descripción paso a paso de la construcción de un componente real y de cierta complejidad. Podrás descubrir cómo, sólo utilizando el estándar, se pueden hacer cosas muy interesantes y completas.

¿Qué pasa con import y los web components?

¿Qué pasa con import y los web components?

Uno de los más controvertidos pilares de los componentes web ha sido el HTML Import. Considerado en estos momentos como una funcionalidad discontinuada, debemos conocer como sacar el máximo partido la instrucción import de Javascipt para gestionar la carga de nuestros componentes.