sql >> Base de Datos >  >> NoSQL >> MongoDB

Chat en tiempo real con Modulus y Node.js

En este tutorial, le mostraré cómo implementar una aplicación de chat en tiempo real con Node.js, Socket.IO y MongoDB, y luego implementaremos esta aplicación en Modulus juntos.

Antes que nada, déjame mostrarte el aspecto final de la aplicación que tendremos al final del artículo.

Node.js será el núcleo de la aplicación, con Express como MVC, MongoDB para la base de datos y Socket.IO para la comunicación en tiempo real. Cuando hayamos terminado, implementaremos nuestra aplicación en Modulus. La parte de MongoDB realmente existe dentro de Modulus.

1. Escenario

  1. John quiere usar nuestra aplicación y la abre en el navegador.
  2. En la primera página, selecciona un apodo para usar durante el chat e inicia sesión para chatear.
  3. En el área de texto escribe algo y presiona Enter.
  4. El texto se envía a un servicio RESTful (Express) y este texto se escribe en MongoDB.
  5. Antes de escribir en MongoDB, el mismo texto se transmitirá a los usuarios que actualmente están conectados a la aplicación de chat.

Como puede ver, esta es una aplicación muy simple, pero cubre casi todo para una aplicación web. No hay un sistema de canales en esta aplicación, pero puede bifurcar el código fuente e implementar el módulo de canales para practicar.

2. Diseño de proyectos desde cero

Intentaré explicar primero las pequeñas piezas del proyecto y combinarlas al final. Comenzaré desde la parte trasera hasta la parte delantera. Entonces, comencemos con los objetos de dominio (modelos MongoDB).

2.1. Modelo

Para la abstracción de la base de datos, usaremos Mongoose. En este proyecto, solo tenemos un modelo llamado Message . Este modelo de mensaje solo contiene text , createDate ,  y author . No hay un modelo para el autor como User porque no implementaremos completamente un sistema de registro/inicio de sesión de usuario. Habrá una página simple que proporciona apodos, y este apodo se guardará en una cookie. Esto se usará en el Message modelo como texto en el author campo. Puede ver un modelo JSON de ejemplo a continuación:

{

    text: "Hi, is there any Full Stack Developer here?"

    author: "john_the_full_stack",

    createDate: "2015.05.15"

}

Para crear documentos como este, puede implementar un modelo usando las siguientes funciones de Mongoose:

var mongoose = require('mongoose')



var Message = new mongoose.Schema({

    author: String,

    message: String,

    createDate: {

        type: Date,

        default: Date.now

    }

});



mongoose.model('Message', Message)

Simplemente importe el módulo Mongoose, defina su modelo con sus campos y atributos de campo en formato JSON, y cree un modelo con el nombre Message . Este modelo se incluirá en las páginas que desee utilizar.

Tal vez tenga una pregunta sobre por qué estamos almacenando el mensaje en la base de datos, cuando ya transmitimos este mensaje al usuario en el mismo canal. Es cierto que no tienes que almacenar mensajes de chat, pero solo quería explicar la capa de integración de la base de datos. De todos modos, usaremos este modelo en nuestro proyecto dentro de los controladores. ¿Controladores?

2.2. Controlador

Como dije antes, usaremos Express para la parte de MVC. Y C   aquí representa el Controller . Para nuestros proyectos, solo habrá dos puntos finales para la mensajería. Uno de ellos es para cargar mensajes de chat recientes y el segundo es para manejar mensajes de chat enviados para almacenarlos en la base de datos y luego transmitirlos al canal.

.....

app.get('/chat', function(req, res){

    res.sendFile(__dirname + '/index.html');

});



app.get('/login', function(req, res){

    res.sendFile(__dirname + '/login.html');

});



app.post('/messages', function(req, res, next) {

    var message = req.body.message;

    var author = req.body.author;

    var messageModel = new Message();

    messageModel.author = author;

    messageModel.message = message;

    messageModel.save(function (err, result) {

       if (!err) {

           Message.find({}).sort('-createDate').limit(5).exec(function(err, messages) {

               io.emit("message", messages);

           });

           res.send("Message Sent!");

       } else {

           res.send("Technical error occurred!");

       }

    });

});



app.get('/messages', function(req, res, next) {

    Message.find({}).sort('-createDate').limit(5).exec(function(err, messages) {

        res.json(messages);

    });

});

.....

Los controladores primero y segundo son solo para servir archivos HTML estáticos para las páginas de chat e inicio de sesión. El tercero es para manejar la solicitud de publicación a /messages   punto final para la creación de nuevos mensajes. En este controlador, en primer lugar, el cuerpo de la solicitud se convierte al modelo de mensaje y, a continuación, este modelo se guarda en la base de datos mediante la función Mongoose save. . 

No profundizaré mucho en Mongoose; puede consultar la documentación para obtener más detalles. Puede proporcionar una función de devolución de llamada para la función de guardar para verificar si hay algún problema o no. Si tiene éxito, hemos obtenido los últimos cinco registros ordenados en orden descendente por createDate , y he transmitido cinco mensajes a los clientes del canal.

Ok, hemos terminado MC .  Cambiemos a View parte.

2.3. Ver

En general, un motor de plantillas como Jade, EJS, Handlebars, etc., se puede usar dentro de Express. Sin embargo, solo tenemos una página, y ese es un mensaje de chat, así que lo serviré de forma estática. En realidad, como dije anteriormente, hay dos controladores más para servir esta página HTML estática. Puede ver lo siguiente para servir una página HTML estática.

app.get('/chat', function(req, res){

    res.sendFile(__dirname + '/index.html');

});



app.get('/login', function(req, res){

    res.sendFile(__dirname + '/login.html');

});

Este punto final simplemente sirve index.html y login.html mediante res.sendFile . Ambos  index.html y login.html están en la misma carpeta que server.js, por lo que usamos __dirname antes del nombre del archivo HTML.

2.4. Frontal

En la página de inicio, he usado Bootstrap y no hay necesidad de explicar cómo logré hacerlo. Simplemente, he enlazado una función a un cuadro de texto, y cada vez que presiona Intro  clave o Enviar  botón, el mensaje se enviará al servicio back-end.

Esta página también tiene un archivo js requerido de Socket.IO para escuchar el canal llamado message . El módulo Socket.IO ya está importado en el back-end, y cuando usa este módulo en el lado del servidor, agrega automáticamente un punto final para servir el archivo Socket.IO js, pero usamos el que se sirve desde cdn <script src="//cdn.socket.io/socket.io-1.3.5.js"></script> . Siempre que llegue un nuevo mensaje a este canal, se detectará automáticamente y la lista de mensajes se actualizará con los últimos cinco mensajes.

<script>

        var socket = io();

        socket.on("message", function (messages) {

            refreshMessages(messages);

        });



        function refreshMessages(messages) {

            $(".media-list").html("");

            $.each(messages.reverse(), function(i, message) {

                $(".media-list").append('<li class="media"><div class="media-body"><div class="media"><div class="media-body">'

                + message.message + '<br/><small class="text-muted">' + message.author + ' | ' + message.createDate + '</small><hr/></div></div></div></li>');

            });

        }



        $(function(){



            if (typeof $.cookie("realtime-chat-nickname") === 'undefined') {

                window.location = "/login"

            } else {

                $.get("/messages", function (messages) {

                    refreshMessages(messages)

                });



                $("#sendMessage").on("click", function() {

                    sendMessage()

                });



                $('#messageText').keyup(function(e){

                    if(e.keyCode == 13)

                    {

                        sendMessage();

                    }

                });

            }



            function sendMessage() {

                $container = $('.media-list');

                $container[0].scrollTop = $container[0].scrollHeight;

                var message = $("#messageText").val();

                var author = $.cookie("realtime-chat-nickname");

                $.post( "/messages", {message: message, author: author}, function( data ) {

                    $("#messageText").val("")

                });

                $container.animate({ scrollTop: $container[0].scrollHeight }, "slow");

            }

        })

    </script>

Hay una verificación más en el código anterior:la parte de la cookie. Si no ha elegido ningún apodo para el chat, significa que la cookie no está configurada para el apodo y será redirigido automáticamente a la página de inicio de sesión.

De lo contrario, los últimos cinco mensajes se obtendrán mediante una simple llamada Ajax a /messages punto final De la misma manera, siempre que haga clic en Enviar o pulsa el botón Intro key, el mensaje de texto se obtendrá del cuadro de texto y el apodo se obtendrá de la cookie, y esos valores se enviarán al servidor con una solicitud posterior. Aquí no hay una verificación estricta para el apodo, porque quería centrarme en la parte en tiempo real, no en la parte de autenticación del usuario.

Como puede ver, la estructura general del proyecto es muy simple. Vayamos a la parte del despliegue. Como dije anteriormente, usaremos Modulus, uno de los mejores PaaS para implementar, escalar y monitorear su aplicación en el idioma que elija.

3. Despliegue

3.1. Requisitos

Lo primero que me viene a la mente es mostrarle cómo implementar, pero para una implementación exitosa, necesitamos una base de datos que funcione. Veamos cómo crear una base de datos en Modulus y luego realizar la implementación.

Vaya al tablero de Modulus después de crear una cuenta. Haga clic en Bases de datos  a la izquierda y haga clic en Crear base de datos.

Complete los campos requeridos en el formulario emergente como se muestra a continuación.

Cuando complete los campos obligatorios y haga clic en Crear,  creará una base de datos MongoDB para usted y verá la URL de su base de datos en la pantalla. Usaremos MONGO URI ,  así que copie ese URI.

En nuestro proyecto, Mongo URI se obtiene de la variable de entorno MONGO_URI , y debe configurar esa variable de entorno en el tablero. Vaya al panel, haga clic en Proyectos seleccione su proyecto en la lista y haga clic en Administración en el menú de la izquierda. En esta página, verá la sección de variables de entorno cuando se desplace hacia abajo en la página, como se muestra a continuación.

Puede realizar la implementación en Modulus de dos formas: 

  • subir el archivo ZIP del proyecto usando el tablero
  • implementación desde la línea de comandos mediante Modulus CLI

Continuaré con la opción de línea de comandos, porque la otra es fácil de hacer. En primer lugar, instale Modulus CLI:

npm install -g modulus

Vaya a la carpeta de su proyecto y ejecute el siguiente comando para iniciar sesión en Modulus.

modulus login

Cuando ejecute el comando anterior, se le pedirá que ingrese un nombre de usuario y una contraseña:

Si ha creado una cuenta usando GitHub, puede usar --github opción.

modulus login --github

Ahora ha iniciado sesión en Modulus y es hora de crear un proyecto. Use el siguiente comando para crear un proyecto:

modulus project create "Realtime Chat"

Cuando ejecute esta función, se le preguntará por el tiempo de ejecución. Selecciona la primera opción, que es Node.js, y la segunda te pedirá el tamaño del servo, y puedes mantenerlo como predeterminado.

Hemos creado un proyecto y esta vez implementaremos nuestro proyecto actual en Modulus. Ejecute el siguiente comando para enviar el proyecto actual al Chat en tiempo real proyecto en el lado de Modulus.

modulus deploy

Implementará su proyecto y obtendrá la URL de su proyecto en ejecución al final del mensaje de implementación exitosa:

Realtime Chat running at realtime-chat-46792.onmodulus.net

Como puede ver, ¡la implementación en Modulus es muy fácil!

Modulus CLI tiene comandos muy útiles para usar durante la implementación de su proyecto o en tiempo de ejecución. Por ejemplo, para seguir los registros de su proyecto en ejecución, puede usar modulus project logs tail , para crear una base de datos MongoDB use modulus mongo create <db-name> , para establecer una variable de entorno, use modulus env set <key> <value> , etc. Puede ver una lista completa de comandos utilizando la ayuda de Modulus.