History: Chat con socket.io

Revision made 7 years ago by Francisco Presencia. Go to the last revision.

En esta lección aprenderéis cómo hacer un chat en tiempo real con Node.js, y socket.io. Aprenderemos qué es eso de websockets y para qué es útil.

Websockets es una tecnología de comunicación en tiempo real bidireccional entre los navegadores y servidores. Es útil por ejemplo para hacer server-push en ciertos eventos, algo que hasta ahora sólo se podía hacer con short/long polling.

socket.io es una herramienta alojada en la web homónima cuyo objetivo es facilitar el uso de websockets y que proporciona funcionalidades más avanzadas como namespaces. Esto es muy útil para hacer chats más complejos ya que permite por ejemplo hacer una habitación en cada namespace.

Instalación

Primero que nada seguir la guia de instalación de Introducción y Preparación. Después, una vez estemos en nuestra carpeta del proyecto y hayamos hecho npm init, instalaremos la librería propia server, que nos servirá para crear nuestro back-end:

npm install server --save

Back-end

Para el back-end vamos a usar las funciones que provee server, que ya incluye la librería socket.io. Como el back-end va a ser sencillo vamos a hacerlo en sólo 2 archivos de código. Primero creamos nuestro punto de entrada, index.js:

// index.js
const server = require('server');
const { get, socket } = server.router;
const { file } = server.reply;
const chat = require('./chat');

// Lanzar el servidor en el puerto 3000
server(

  // Mostrar el archivo principal a todo el mundo
  get('/', file('./public/index.html')),

  // Rutas para el chat
  socket('login',      chat.login),
  socket('message',    chat.message),
  socket('logout',     chat.logout),  // Manual
  socket('disconnect', chat.logout),  // Accidental/cerrar ventana
);

Y después creamos la lógica del chat.js:

// Guardar el nombre del usuario en el back-end y comunicarlo a todos
exports.login = ctx => {
  ctx.socket.name = ctx.data;
  return ctx.io.emit('login', { name: ctx.data.name, time: new Date() });
};

// Cuando alguien envía un mensaje, reenviarlo a todo el mundo
exports.message = ctx => {
  ctx.io.emit('message', { text: ctx.data, time: new Date() });
};

// Cuando alguien hace logout mostrarselo también a todo el mundo
exports.logout = ctx => {
  return ctx.io.emit('logout', { name: ctx.data.name, time: new Date() });
};