Mensajes En Tiempo Real Usando Primus

Primus es un paquete de Node.js, el cual nos ayuda a utilizar otros frameworks de tiempo real para mensajería instantánea, haciéndolo flexible ya que si existe algún bug con el framework que estas usando, cambiarlo, es tan simple como cambiar el valor del transformer. Primus utiliza otros Frameworks como :

  1. BrowserChannel
  2. Engine.IO
  3. Faye
  4. SockJS
  5. uws
  6. WebSockets

En este tutorial vamos a utilizar SockJS sin embargo cambiando el valor del transformer en el código { transformer: 'sockjs' } podemos usar cualquier otra alternativa arriba mencionada.

Pero que usos tiene?

  • Sistemas de Chats
  • Actualizaciones de Base de Datos
  • Actualizar en tiempo real la bolsa de Valores.
  • Si deseas que algo sea actualizado en tiempo real.

Instalación Mensajes En Tiempo Real Usando Primus (server)

Si no as instalado Node.js entonces instalalo en este tutorial no te voy a mostrar como, ya que es tan fácil tan solo como bajarlo la ultima actualización y darle doble click a el setup.exe..

Crea un folder donde tu Primus script va vivir. Para Mensajes En Tiempo Real yo le eh llamando primus al folder. Abre un CMD y navega adentro de el folder que acabamos de crear. Escribe el siguiente comando npm init, si tienes instalado Node.js correctamente este empezara haciéndote preguntas, esta crea un package.json el cual contiene los requisitos que nuestro script necesitara.

Instalación Mensajes En Tiempo Real Usando Primus (server)

Las preguntas que nos ase son sencillas, asegura que cuando te pregunte que nombre darle , no uses mayúsculas o espacios ya que no son permitidas. cuando ayas terminado esto ahora instalamos Primus usando el siguiente comando todavía en el CMD npm install primus --save instalara nuestro packete de Primus y lo salvara como requisito en el package.json.

Listo esto, ya tenemos a Primus instalado sin embargo. Necesitamos también instalara paquetes de tiempo real ya que como les dije, este es un Wrapper el cual ayuda a utilizar otros Frameworks de tiempo real. Instalaremos Sockjs. Escribe este comando en el CMD npm install --save sockjs, ahora si ya podemos jugar con nuestro Mensajes En Tiempo Real Usando Primus.

Ok, Nuestro punto de entrada en el script para nuestro Primus es server.js, recuerdas cuando utilizamos el comando npm init una de las preguntas fue cual el punto de execución de nuestro script y este es server.js, adentro de nuestro folder primus crea este archivo server.js si as seguido todo al pie de la letra tendrás algo parecido a esto.

Instalación Mensajes En Tiempo Real Usando Primus arquitectura del folder

Ahora abrimos nuestro server.js y le agregamos un poco de código para tener nuestro servidor funcionando correctamente.

'use strict';

const Primus = require('primus')
, http = require('http')
, port = process.env.PORT || 8080;

const server = http.createServer()
, primus = new Primus(server, { parser: 'JSON', transformer: 'sockjs' });

server.listen( port, () =>{
    console.log(`Servidor Primus online en puerto ${port} `);
});
primus.on('connection', (spark) => {

    // aguardamos por mensajes de nuestro
    // clientes
    spark.on('data', ( data ) =>{
        // nos cercioramos que sea
        // un objecto
        if( typeof data === 'object' ){
            // por ultimo, observamos
            // que sea tipo string
            // ojo, aquí tienes que
            // escapar los mensajes
            // por seguridad
            if( typeof data.mensajes === 'string' ){
                primus.write( data );
            }

        }
    });
    console.log('connectados');
});

primus.on('disconnection', (spark) => {
    console.log('cliente se desconecto');
});

Explicare un poco el server.js.

const Primus = require('primus')
, http = require('http')
, port = process.env.PORT || 8080;

Las primeras constantes requerimos el modulo de Primus al mismo tiempo creamos mas constantes para el modulo http que esta instalado por defecto en Node.js ademas creamos otra constante llamada port, este es el puerto al que responderá y escuchara por conexiones.

Las siguientes constantes , const server = http.createServer() creamos un servidor http y lo pasamos como parámetro a nuestra constante primus = new Primus(server, { parser: 'JSON', transformer: 'sockjs' });, activamos el parser con JSON para recibir cargas de JSON fácilmente ademas aquí podes cambiar el transformer por alguno que sea soportado por primus.

const server = http.createServer()
, primus = new Primus(server, { parser: 'JSON', transformer: 'sockjs' });

En esta linea server.listen( port, () =>{    console.log(`Servidor Primus online en puerto ${port} `);}); pasamos como parámetro el puerto en este caso 8080 si process.env.PORT no esta definido, nuestro servidor aguardara por conexiones en este puerto, una vez activado y esperando por conexiones printeamos información para saber que todo va bien usando el console.log.

En el siguiente código es donde tendremos el objeto de nuestro cliente que se a conectado con nuestro servidor

primus.on('connection', (spark) => {

    // aguardamos por mensajes de nuestro
    // clientes
    spark.on('data', ( data ) =>{
        // nos cercioramos que sea
        // un objecto
        if( typeof data === 'object' ){
            // por ultimo, observamos
            // que sea typo mensajes
            // ojo, aqui tienes que
            // escapar los mensajes
            // por seguiridad
            if( typeof data.mensajes === 'string' ){
                primus.write( data );
            }

        }
    });
    console.log('connectados');
});

primus.on('disconnection', (spark) => {
    console.log('cliente se desconecto');
});

Usando el evento “connection” el objeto que tiene el callback es nuestro spark (cliente). Ahora aguardamos por un evento tipo “data” que atachamos a nuestro spark con un callback con variable data , esta data contiene objetos que son transmitidos por el cliente y que el servidor a parseado en este caso de índole mensajes ya que es nuestro primus chat el que lo a enviado.

Para hacer mas fácil el debug printemamos a la consola, que nos conectamos, al mismo tiempo atachamos un evento de desconexión en la instancia de primus.

Con esto finalizamos el server.js, el siguiente sera el cliente, ahora inicializa el server.js usando el comando “node server” .

Mensajes En Tiempo Real Usando Primus (el cliente)


Para completar nuestro tutorial, Mensajes En Tiempo Real Usando Primus vamos hacer una simple interfaze de chat utilizaremos jQuery y Boostrap 4, nada complicado muy simple..

Primus expone la librería para el cliente en http://localhost:8080/primus/primus.js donde el puerto 8080 es el que usamos para que el servidor Primus observe conexiones de los clientes. En un folder diferente creas un simple index.html y pegaremos el siguiente código:

Explicare un poco el código del cliente pero algunas partes seguramente ya son familiares o mas bien depreciadas, aguardamos el evento window.onload y instanciamos nuestro cliente y lo conectamos con el método Primus#connect a la URL http://localhost:8080, la constante primus esta disponible ya podemos esperar por los eventos “open“, “data” y “close“.

// conectamos a nuestro servidor Primus
                const primus = Primus.connect('http://localhost:8080');

Creamos un contenedor $container_messages que contendrá los mensajes que recibimos así mismo $chat_input que observara por “strings” en el input del textarea, otra varibale $messages_container_ul que es el contendor individual de los mensajes recibidos. Por ultimo una variable conectados que nos indica cuando estamos conectados o no..

// elemento que contiene nuestro ul
                const $container_messages = $('.container-messages');
                // nuestro elementos
                const $chat_input = $('.chat-input');
                // elemento que contiene los mensajes
                const $messages_container_ul= $('.messages');
                // observamos la coneccion
                let conectados = false;

Con el método “on” que existe en el objeto de primus aguardamos por el evento “open” para cambiar el estado de nuestra variable conectados, cambiándola a true, cuando el estado de esta variable es verdadera y escribimos un mensaje en nuestro chat para mostrar que estamos conectados.

primus.on('open', () => {
                    conectados = true;
                    write_message(`connectados al servidor...`);
                });

En nuestra variable $chat_input observamos el evento “keyup” chequeamos que el evento sea que hemos presionado “enter” en nuestro teclado y estemos conectado, al mismo tiempo nos cercioramos que la variable $mensaje no sea un “string” vació mandamos nuestro mensaje con el método primus#write enseguida limpiamos nuestro input.

// aguardamos que el usuario presion ENTER
                $chat_input.keyup( ( ev ) => {
                    if ( ev.keyCode === 13 && conectados ) {
                        let $mensaje = $.trim( $chat_input.val() );
                        // si el mensaje no es un empty string
                        if( $mensaje !== "" ){
                            primus.write({'mensajes' : $mensaje});
                        }
                        //limpiamos el input
                        $chat_input.val("");
                    }
                });

Ahora aguardamos por el evento “data” que es un evento en el servidor cuando este recibe data de otros conectado y de nosostros mismos. Nos cercioramos que sea de tipo “objeto” y que una de sus propiedades data.mensajes sea de tipo “string” y lo insertamos usando la función que creamos para esta índole solamente.

// evento que contiene los datos
                // que el servidor Primus
                // a obtenido de los usuarios
                primus.on('data', ( data )=>{
                    if( typeof data === 'object' ){
                        // nos aseguramos que es un string
                        if( typeof data.mensajes === 'string' ){
                            write_message(data.mensajes);
                        }
                    }
                });

En el evento “close” de nuestro primus hacemos limpieza dándole el valor falso a conectados y escribiendo que nos desconectamos.

// recivimos evento que
                // nos desconnectamos
                primus.on('close', () => {
                    conectados = false;
                    write_message(`Nos desconectamos!`);
                });

Ahora, creamos una función simple que pegara los mensajes al contenedor de nuestro chat, la llamamos write_messages creamos un tag “li” con clase “message” agregamos el mensaje recibido a el “li$mensaje.text( message );, entonces lo pegamos a nuestro contenedor de mensajes “ul” $messages_container_ul.append( $mensaje );, enseguida nos cercioramos que el chat “scroll” lo haga automáticamente.

/** simple funcion que inserta los mensajes */
                function write_message( message ){
                    // creamos elemento
                    let $mensaje = $('<li class="message">');
                    // lo insertamos en nuestro mensaje elemento
                    $mensaje.text( message );
                    // por ultimo lo insertamos en el
                    // contenedor de mensajes
                    $messages_container_ul.append( $mensaje );
                    // ahora , scroll los mensajes automaticamente
                    $container_messages.scrollTop($container_messages[0].scrollHeight);
                }

Conclusión

Primus es un wrapper maravilloso muy fácil de usar ademas que se le puede poner plugin para hacerlo mas útil y fácil de manejar, tiene otros métodos para mandar mensajes solo al especifico spark etc.. échale un ojo y leete su github les dejo el cliente del chat por si acaso quieren ir de una vez a lo que vinieron para no aburrirse.

<!DOCTYPE html>
<html lang="en_US" xml:lang="en_US" xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    <meta name="viewport" content="width=device-width, initial-scale=1.0 , user-scalable=no"/>
    <title>Mensajes En Tiempo Real Usando Primus</title>
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet">
    <style>
        * {
            font-family:'Times New Roman', Times, serif;
        }
        .container-messages{
            height: 500px;
            overflow-y:scroll;
        }
        .messages{
            list-style-type: none;
        }
        .messages li{
            padding:5px;
            margin:5px;
            border-bottom: 1px solid rgb(114, 114, 163);
        }
    </style>
    </head>
    <body>
        <nav class="navbar navbar-light bg-light">
            <a class="navbar-brand" href="https://www.vcomputadoras.com/mensajes-en-tiempo-real-usando-primus" alt="Mensajes En Tiempo Real Usando Primus vamos hacer una simple interfaze de chat utilizaremos jQuery y Boostrap 4">
              <img src="./images/vcomputadoras815x691_200x200_30x30.png" width="30" height="30" class="d-inline-block align-top" alt="Mensajes En Tiempo Real Usando Primus">
              Primus Chat
            </a>
          </nav>
        <div class="container-fluid">
            <div class="row">
                <div class="col container-messages">
                    <ul class="messages"></ul>
                </div>
            </div>
            <div class="form-group">
                <textarea class="form-control chat-input" rows="1" cols="50" placeholder="Escribe Aqui!"></textarea>
            </div>
        </div>
        <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js" defer></script>
        <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" defer></script>
        <script src="http://localhost:8080/primus/primus.js" defer></script>
        <script>
            window.onload = () =>{
                // conectamos a nuestro servidor Primus
                const primus = Primus.connect('http://localhost:8080');
                // elemento que contiene nuestro ul
                const $container_messages = $('.container-messages');
                // nuestro elementos
                const $chat_input = $('.chat-input');
                // elemento que contiene los mensajes
                const $messages_container_ul= $('.messages');
                // observamos la coneccion
                let conectados = false;
                // aguardamos que el usuario presion ENTER
                $chat_input.keyup( ( ev ) => {
                    if ( ev.keyCode === 13 && conectados ) {
                        let $mensaje = $.trim( $chat_input.val() );
                        // si el mensaje no es un empty string
                        if( $mensaje !== "" ){
                            primus.write({'mensajes' : $mensaje});
                        }
                        //limpiamos el input
                        $chat_input.val("");
                    }
                });
                // evento que nos indica que tenemos coneccion
                // al servidor Primus
                primus.on('open', () => {
                    conectados = true;
                    write_message(`connectados al servidor...`);
                });
                // evento que contiene los datos
                // que el servidor Primus
                // a obtenido de los usuarios
                primus.on('data', ( data )=>{
                    if( typeof data === 'object' ){
                        // nos aseguramos que es un string
                        if( typeof data.mensajes === 'string' ){
                            write_message(data.mensajes);
                        }
                    }
                });
                // recivimos evento que
                // nos desconnectamos
                primus.on('close', () => {
                    conectados = false;
                    write_message(`Nos desconectamos!`);
                });

                /** simple funcion que inserta los mensajes */
                function write_message( message ){
                    // creamos elemento
                    let $mensaje = $('<li class="message">');
                    // lo insertamos en nuestro mensaje elemento
                    $mensaje.text( message );
                    // por ultimo lo insertamos en el
                    // contenedor de mensajes
                    $messages_container_ul.append( $mensaje );
                    // ahora , scroll los mensajes automaticamente
                    $container_messages.scrollTop($container_messages[0].scrollHeight);
                }
            }
        </script>
    </body>
</html>
Mensajes En Tiempo Real Usando Primus