Hands-On: Build a Node.js-powered Chatroom Web App (#3)

Práctica: Cree una aplicación web de sala de chat con tecnología de Node.js (tercera parte)

Este Nodo.js La serie de tutoriales lo ayudará a crear una aplicación web de sala de chat en tiempo real con tecnología de Node.js completamente implementada en la nube. A lo largo de la serie, aprenderá a configurar Nodo.js en su máquina Windows, cómo desarrollar una interfaz web con Rápidocómo implementar aplicaciones rápidas de un nodo para Azurcómo utilizar enchufe para agregar una capa en tiempo real y cómo implementarlo todo junto.

Nivel: Principiante a Intermedio: se espera que sepa HTML5 y JavaScript

Parte 3: creación de un backend de sala de chat con Node.js, Socket.IO y Mongo

Bienvenido a la Parte 2 de la serie de tutoriales prácticos de Node.js: Cree una aplicación web de sala de chat con la tecnología de Node.js. En esta entrega, le mostraré cómo usar su aplicación Node.js basada en express existente para crear un backend de sala de chat con soporte WebSocket.

¿Qué son los WebSockets? ¿Qué es Socket.IO?

WebSocket es un protocolo diseñado para permitir que las aplicaciones web creen un canal full-duplex sobre TCP (es decir, para tener una comunicación bidireccional) entre el navegador web y un servidor web. Es totalmente compatible con HTTP y utiliza el puerto TCP número 80. WebSocket ha permitido que las aplicaciones web se conviertan en tiempo real y admitan interacciones avanzadas entre el cliente y el servidor. Es compatible con varios navegadores, incluidos Internet Explorer, Google Chrome, Firefox, Safari y Opera.

Zócalo.IO es una biblioteca de JavaScript y un módulo de Node.js que le permite crear aplicaciones de comunicación basadas en eventos bidireccionales en tiempo real de manera simple y rápida. Simplifica significativamente el proceso de uso de WebSockets. Usaremos Socket.IO v1.0 para hacer nuestra aplicación de sala de chat.

Agregando Socket.IO a package.json

Package.json es un archivo que contiene varios metadatos relevantes para el proyecto, incluidas sus dependencias. NPM puede usar este archivo para descargar los módulos requeridos por el proyecto. Mira esto explicación interactiva de package.json y lo que puede contener.
Agreguemos Socket.IO al proyecto como una dependencia. Hay dos maneras de hacerlo.

1. Si ha estado siguiendo la serie de tutoriales y tiene un proyecto en la configuración de Visual Studio, haga clic con el botón derecho en la parte NPM del proyecto y seleccione «Instalar nuevos paquetes NPM…»

clip_image002

Una vez que se haya abierto la ventana, busque «socket.io», seleccione el resultado superior y marque la casilla de verificación «Agregar a paquete.json». Haga clic en el botón «Instalar paquete». Esto instalará Socket.IO en su proyecto y lo agregará al archivo package.json.

clip_image004

paquete.json

{
  "name": "NodeChatroom",
  "version": "0.0.0",
  "description": "NodeChatroom",
  "main": "app.js",
  "author": {
    "name": "Rami Sayar",
    "email": ""
  },
  "dependencies": {
    "express": "3.4.4",
    "jade": "*",
    "socket.io": "^1.0.6",
    "stylus": "*"
  }
}

2. Si está en OS X o Linux, puede lograr la misma acción que la anterior ejecutando el siguiente comando en la raíz de la carpeta de su proyecto.

npm install --save socket.io

Agregando Socket.IO a app.js

El siguiente paso es agregar Socket.IO a app.js. Puede lograr esto reemplazando el siguiente código.

http.createServer(app).listen(app.get('port'), function(){
  console.log('Express server listening on port ' + app.get('port'));
});

Para ser reemplazado con:

var serve = http.createServer(app);
var io = require('socket.io')(serve);

serve.listen(app.get('port'), function () {
    console.log('Express server listening on port ' + app.get('port'));
});

Esto capturará el servidor HTTP en una variable llamada servir y pasará ese servidor HTTP para que el módulo Socket.IO pueda conectarse a él. El último bloque de código toma la variable de servicio y ejecuta la función de escucha que inicia el servidor HTTP.

Registro de un usuario que se une y se va

Idealmente, queremos registrar a un usuario que se une a la sala de chat. El siguiente código logra eso al conectar una función de devolución de llamada para que se ejecute en cada evento de «conexión» a través de WebSocket a nuestro servidor HTTP. En la función de devolución de llamada, llamamos a console.log para registrar que un usuario se conectó. Podemos agregar este código después de llamar a serve.listen.

io.on('connection', function (socket) {
    console.log('a user connected');
});

Para hacer lo mismo cuando un usuario se desconecta, tenemos que conectar el evento «desconectar» para cada socket. Agregue el siguiente código dentro después del registro de la consola del bloque de código anterior.

    socket.on('disconnect', function () {
        console.log('user disconnected');
    });

Finalmente, el código se verá así:

io.on('connection', function (socket) {
    console.log('a user connected');
    socket.on('disconnect', function () {
        console.log('user disconnected');
    });
});

Difusión de un mensaje recibido en el canal de chat

Socket.IO nos da una función llamada emit para enviar eventos.
Cualquier mensaje recibido en el canal de «chat» se transmitirá a todas las demás conexiones en este socket llamando a emit con el indicador de transmisión en la devolución de llamada.

socket.on('chat', function (msg) {
    socket.broadcast.emit('chat', msg);
});

Finalmente, el código se verá así:

io.on('connection', function (socket) {
    console.log('a user connected');
    socket.on('disconnect', function () {
        console.log('user disconnected');
    });
 
    socket.on('chat', function (msg) {
        socket.broadcast.emit('chat', msg);
    });
});

Guardar mensajes en una base de datos NoSQL

La sala de chat debe guardar los mensajes de chat en un almacén de datos simple. Normalmente, hay dos formas de guardar en una base de datos en Node; puede usar un controlador específico de la base de datos o puede usar un ORM. En este tutorial, le mostraré cómo guardar los mensajes en MongoDB. Por supuesto, puede usar cualquier otra base de datos que desee, incluidas las bases de datos SQL como PostgreSQL o MySQL.

Debe asegurarse de tener un MongoDB para conectarse. Puede utilizar un servicio de terceros para alojar su MongoDB, como MongoHQ o MongoLab. Mira esto tutorial para ver como puedes crear un MongoDB utilizando el complemento MongoLab en Azure. Puede dejar de leer cuando llegue a la sección «Crear la aplicación», solo asegúrese de guardar MONGOLAB_URI en algún lugar al que pueda acceder fácilmente más tarde.

Una vez que haya creado un MongoDB y tenga el MONGOLAB_URI para la base de datos, en Información de conexión que ha copiado en su portapapeles, querrá asegurarse de que el URI esté disponible para la aplicación. No es una buena práctica agregar información confidencial como este URI en su código o en un archivo de configuración en su herramienta de administración de código fuente.

Puede agregar el valor a la lista Cadenas de conexión en el menú Configuración de su aplicación web de Azure (como en el tutorial que usó) o puede agregarlo a la lista Configuración de la aplicación (con el nombre «CUSTOMCONNSTR_MONGOLAB_URI»). En su máquina local, puede agregarlo a las variables de entorno con el nombre «CUSTOMCONNSTR_MONGOLAB_URI» y el valor del URI.

El siguiente paso es agregar soporte para MongoDB a nuestro proyecto. Puede hacerlo agregando la siguiente línea al objeto de dependencias en package.json. Asegúrese de guardar los cambios en el archivo.

"mongodb": "^1.4.10",

Haga clic con el botón derecho en la parte NPM del proyecto en el Explorador de soluciones para revelar el menú contextual del botón derecho. Haga clic en «Instalar paquetes faltantes» en el menú de contenido para instalar el paquete MongoDB para que pueda usarse como un módulo.

clip_image005

Queremos importar ese módulo para poder usar el objeto del cliente MongoDB en app.js. Puede agregar las siguientes líneas de código después de las primeras llamadas a la función require(»), como en la línea 11.

var mongo = require('mongodb').MongoClient;

Queremos conectarnos a la base de datos usando la URI que tenemos en la variable de entorno CUSTOMCONNSTR_MONGOLAB_URI. Una vez conectado, queremos insertar el mensaje de chat recibido en la conexión del socket.

mongo.connect(process.env.CUSTOMCONNSTR_MONGOLAB_URI, function (err, db) {
    var collection = db.collection('chat messages');
    collection.insert({ content: msg }, function (err, o) {
        if (err) { console.warn(err.message); }
        else { console.log("chat message inserted into db: " + msg); }
    });
});

Como puede ver en el código anterior, usamos el objeto process.env para obtener el valor de la variable de entorno. Entramos en una colección en la base de datos y llamamos a la función de inserción con el contenido en un objeto.

Cada mensaje ahora se guarda en nuestra base de datos MongoDB.

Emisión de los últimos 10 mensajes recibidos

Por supuesto, no queremos que nuestros usuarios se sientan perdidos una vez que se unen a la sala de chat, por lo que debemos asegurarnos de enviar los últimos 10 mensajes recibidos al servidor para que, al menos, podamos darles algo de contexto. Para hacer eso, necesitamos conectar mongo. En este caso, me abstengo de envolver todo el código del socket con una conexión a la base de datos para que pueda seguir funcionando el servidor incluso si pierde la conexión a la base de datos.

También querremos ordenar y limitar mi consulta a los últimos 10 mensajes, usaremos el _id generado por MongoDB ya que contiene una marca de tiempo (aunque en situaciones más escalables, querrá crear una marca de tiempo dedicada en el mensaje de chat) y nosotros llamará a la función de límite para limitar los resultados a solo 10 mensajes.

Transmitiremos los resultados de MongoDB para que pueda emitirlos lo antes posible a la sala de chat a medida que lleguen.

mongo.connect(process.env.CUSTOMCONNSTR_MONGOLAB_URI, function (err, db) {
    var collection = db.collection('chat messages')
    var stream = collection.find().sort({ _id : -1 }).limit(10).stream();
    stream.on('data', function (chat) { socket.emit('chat', chat.content); });
}); 

El código anterior hace el trabajo como se explica en los párrafos anteriores.

Implementación en Azure

Puede volver a implementar en Azure siguiendo los tutoriales anteriores (como parte 2).

Conclusión

En conclusión, tenemos un sistema de chat capaz de transmitir un mensaje recibido a través de WebSockets a todos los demás clientes conectados. El sistema guarda el mensaje en la base de datos y recupera los últimos 10 mensajes para dar contexto a cada nuevo usuario que se une a la sala de chat.

¡Estén atentos para la Parte 4! La Parte 4 — Creación de una interfaz de usuario de sala de chat con Bootstrap — se publicará pronto en Noupe y también se encuentra en mi blog aquí. Puedes mantenerte actualizado sobre este y otros artículos siguiendo mi cuenta de twitter: @ramisayar.

Más partes de la serie en MSDN

Parte 1 – Introducción a Node.js
Parte 2: Bienvenido a Express con Node.js y Azure

Parte 3 – Construcción de un backend con Node, Mongo y Socket.IO
Parte 4: creación de una interfaz de usuario de sala de chat con Bootstrap
Parte 5: Conexión de la sala de chat con WebSockets
Parte 6: el final y la depuración de aplicaciones de nodos remotos

Más aprendizaje para Node en Azure

Para un aprendizaje más profundo sobre el nodo, mi curso es disponible aquí en la Academia Virtual de Microsoft.

O algunos videos de formato más corto sobre temas de nodos similares:

Este artículo es parte de la serie de tecnología de desarrollo web de Microsoft. Estamos emocionados de compartir Microsoft Edge (anteriormente Proyecto Spartan) y es nuevo motor de renderizado contigo. Obtenga máquinas virtuales gratuitas o realice pruebas de forma remota en su dispositivo Mac, iOS, Android o Windows @ moderno.ES.

Código fuente completo de app.js para su conveniencia

//
/**
 * Module dependencies.
 */

var express = require('express');
var routes = require('./routes');
var user = require('./routes/user');
var http = require('http');
var path = require('path');

var mongo = require('mongodb').MongoClient;

var app = express();

// all environments
app.set('port', process.env.PORT || 3000);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.json());
app.use(express.urlencoded());
app.use(express.methodOverride());
app.use(app.router);
app.use(require('stylus').middleware(path.join(__dirname, 'public')));
app.use(express.static(path.join(__dirname, 'public')));

// development only
if ('development' == app.get('env')) {
  app.use(express.errorHandler());
}

app.get('/', routes.index);
app.get('/users', user.list);

var serve = http.createServer(app);
var io = require('socket.io')(serve);

serve.listen(app.get('port'), function () {
    console.log('Express server listening on port ' + app.get('port'));
});

io.on('connection', function (socket) {
    console.log('a user connected');

    mongo.connect(process.env.CUSTOMCONNSTR_MONGOLAB_URI, function (err, db) {
        var collection = db.collection('chat messages')
        var stream = collection.find().sort({ _id : -1 }).limit(10).stream();
        stream.on('data', function (chat) { socket.emit('chat', chat); });
    });

    socket.on('disconnect', function () {
        console.log('user disconnected');
    });

    socket.on('chat', function (msg) {
        mongo.connect(process.env.CUSTOMCONNSTR_MONGOLAB_URI, function (err, db) {
            var collection = db.collection('chat messages');
            collection.insert({ content: msg }, function (err, o) {
                if (err) { console.warn(err.message); }
                else { console.log("chat message inserted into db: " + msg); }
            });
        });

        socket.broadcast.emit('chat', msg);
    });
});

(dpe)


#Práctica #Cree #una #aplicación #web #sala #chat #con #tecnología #Nodejs #tercera #parte

Publicaciones Similares

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *