Cómo utilizar eventos enviados por el servidor en Node.js para crear una aplicación en tiempo real

Introducción

Índice
  1. Introducción
  • Prerrequisitos
  • Paso 1: creación del backend de SSE Express
  • Paso 2: Prueba del backend
  • Paso 3: creación de la interfaz de usuario de la aplicación web React
  • Paso 4 – Prueba del frontend
  • Conclusión
  • Server-Sent Events (SSE) es una tecnología basada en HTTP. Del lado del cliente, proporciona una API llamada EventSource(parte del estándar HTML5) que nos permite conectarnos al servidor y recibir actualizaciones de este.

    Antes de tomar la decisión de utilizar eventos enviados por el servidor, debemos tener en cuenta dos aspectos muy importantes:

    • Solo permite la recepción de datos desde el servidor (unidireccional)
    • Los eventos están limitados a UTF-8 (sin datos binarios)

    Si su proyecto solo recibe algo como precios de acciones o información de texto sobre algo en progreso, es un candidato para usar eventos enviados por el servidor en lugar de una alternativa como WebSockets .

    En este artículo, creará una solución completa para el backend y el frontend para manejar la información en tiempo real que fluye del servidor al cliente. El servidor se encargará de enviar nuevas actualizaciones a todos los clientes conectados y la aplicación web se conectará al servidor, recibirá estas actualizaciones y las mostrará.

    Prerrequisitos

    Para seguir este tutorial, necesitarás:

    • Un entorno de desarrollo local para Node.js. Sigue Cómo instalar Node.js y crear un entorno de desarrollo local .
    • Familiaridad con Express.
    • Familiaridad con React (y hooks ).
    • Se utiliza cURL para verificar los puntos finales. Es posible que ya esté disponible en su entorno o que deba instalarlo. También será útil tener cierta familiaridad con el uso de herramientas y opciones de línea de comandos.

    Este tutorial fue verificado con cURL v7.64.1, Node v15.3.0, npmv7.4.0, expressv4.17.1, body-parserv1.19.0, corsv2.8.5 y reactv17.0.1.

    Paso 1: creación del backend de SSE Express

    En esta sección, creará un nuevo directorio de proyecto. Dentro del directorio de proyecto habrá un subdirectorio para el servidor. Más adelante, también creará un subdirectorio para el cliente.

    Primero, abre tu terminal y crea un nuevo directorio de proyecto:

    1. mkdir node-sse-example

    Navegue hasta el directorio del proyecto recién creado:

    1. cd node-sse-example

    A continuación, cree un nuevo directorio de servidor:

    1. mkdir sse-server

    Navegue hasta el directorio del servidor recién creado:

    1. cd sse-server

    Inicializar un nuevo npmproyecto:

    1. npm init -y

    Instalar express, body-parser, y cors:

    1. npm install express@4.17.1 body-parser@1.19.0 cors@2.8.5 --save

    Esto completa la configuración de dependencias para el backend.

    En esta sección, desarrollará el backend de la aplicación. Deberá admitir estas funciones:

    • Realizar un seguimiento de las conexiones abiertas y los cambios de transmisión cuando se agregan nuevos datos
    • GET /eventsPunto final para registrarse para actualizaciones
    • POST /factspunto final para nuevos hechos
    • GET /statuspunto final para saber cuántos clientes se han conectado
    • corsmiddleware para permitir conexiones desde la aplicación frontend

    Utilice la primera sesión de terminal que se encuentre en el sse-serverdirectorio. Cree un nuevo server.jsarchivo:

    Abra el server.jsarchivo en su editor de código. Solicite los módulos necesarios e inicialice la aplicación Express:

    servidor sse/servidor.js

    const express = require('express');const bodyParser = require('body-parser');const cors = require('cors');const app = express();app.use(cors());app.use(bodyParser.json());app.use(bodyParser.urlencoded({extended: false}));app.get('/status', (request, response) = response.json({clients: clients.length}));const PORT = 3000;let clients = [];let facts = [];app.listen(PORT, () = {  console.log(`Facts Events service listening at http://localhost:${PORT}`)})

    A continuación, cree el middleware para GETlas solicitudes al /eventspunto final. Agregue las siguientes líneas de código a server.js:

    servidor sse/servidor.js

    // ...function eventsHandler(request, response, next) {  const headers = {    'Content-Type': 'text/event-stream',    'Connection': 'keep-alive',    'Cache-Control': 'no-cache'  };  response.writeHead(200, headers);  const data = `data: ${JSON.stringify(facts)}nn`;  response.write(data);  const clientId = Date.now();  const newClient = {    id: clientId,    response  };  clients.push(newClient);  request.on('close', () = {    console.log(`${clientId} Connection closed`);    clients = clients.filter(client = client.id !== clientId);  });}app.get('/events', eventsHandler);

    El eventsHandlermiddleware recibe los objetos requesty responseque proporciona Express.

    Los encabezados son necesarios para mantener abierta la conexión. El Content-Typeencabezado se establece en 'text/event-stream'y el Connectionencabezado se establece en 'keep-alive'. El Cache-Controlencabezado es opcional, se establece en 'no-cache'. Además, el estado HTTP se establece en 200: el código de estado para una solicitud exitosa.

    Después de que un cliente abre una conexión, los datos factsse convierten en una cadena. Debido a que se trata de un transporte basado en texto, debe convertir la matriz en cadena ; además, para cumplir con el estándar, el mensaje necesita un formato específico. Este código declara un campo llamado datay le asigna la matriz convertida en cadena. El último detalle a destacar es que la nueva línea final doble nnes obligatoria para indicar el final de un evento.

    Se genera A clientIden función de la marca de tiempo y del responseobjeto Express. Estos se guardan en la clientsmatriz. Cuando A clientcierra una conexión, la matriz de clientsse actualiza a filterout that client.

    A continuación, cree el middleware para POSTlas solicitudes al /factpunto final. Agregue las siguientes líneas de código a server.js:

    servidor sse/servidor.js

    // ...function sendEventsToAll(newFact) {  clients.forEach(client = client.response.write(`data: ${JSON.stringify(newFact)}nn`))}async function addFact(request, respsonse, next) {  const newFact = request.body;  facts.push(newFact);  respsonse.json(newFact)  return sendEventsToAll(newFact);}app.post('/fact', addFact);

    El objetivo principal del servidor es mantener a todos los clientes conectados e informados cuando se agregan nuevos datos. El addNestmiddleware guarda el dato, lo devuelve al cliente que realizó POSTla solicitud e invoca la sendEventsToAllfunción.

    sendEventsToAllitera la clientsmatriz y utiliza el writemétodo de cada objeto Express responsepara enviar la actualización.

    Paso 2: Prueba del backend

    Antes de implementar la aplicación web, puede probar su servidor usando cURL:

    En una ventana de terminal, navegue hasta el sse-serverdirectorio de su proyecto y ejecute el siguiente comando:

    1. node server.js

    Mostrará el siguiente mensaje:

    1. OutputFacts Events service listening at http://localhost:3001

    En una segunda ventana de terminal, abra una conexión en espera de actualizaciones con el siguiente comando:

    1. curl -H Accept:text/event-stream http://localhost:3001/events

    Esto generará la siguiente respuesta:

    1. Outputdata: []

    Una matriz vacía.

    En una tercera ventana de terminal, cree una solicitud POST posterior para agregar un nuevo hecho con el siguiente comando:

    1. curl -X POST
    2. -H "Content-Type: application/json"
    3. -d '{"info": "Shark teeth are embedded in the gums rather than directly affixed to the jaw, and are constantly replaced throughout life.", "source": "https://en.wikipedia.org/wiki/Shark"}'
    4. -s http://localhost:3001/fact

    Después de la POSTsolicitud, la segunda ventana del terminal debería actualizarse con el nuevo hecho:

    1. Outputdata: {"info": "Shark teeth are embedded in the gums rather than directly affixed to the jaw, and are constantly replaced throughout life.", "source": "https://en.wikipedia.org/wiki/Shark"}

    Ahora la factsmatriz se rellena con un elemento si cierra la comunicación en la segunda pestaña y la abre nuevamente:

    1. curl -H Accept:text/event-stream http://localhost:3001/events

    En lugar de una matriz vacía, ahora debería recibir un mensaje con este nuevo elemento:

    1. Outputdata: [{"info": "Shark teeth are embedded in the gums rather than directly affixed to the jaw, and are constantly replaced throughout life.", "source": "https://en.wikipedia.org/wiki/Shark"}]

    En este punto, el backend está completamente funcional. Ahora es momento de implementar la EventSourceAPI en el frontend.

    Paso 3: creación de la interfaz de usuario de la aplicación web React

    En esta parte de nuestro proyecto, escribirás una aplicación React que use la EventSourceAPI.

    La aplicación web tendrá el siguiente conjunto de características:

    • Abrir y mantener una conexión con nuestro servidor previamente desarrollado
    • Renderizar una tabla con los datos iniciales
    • Mantenga la tabla actualizada a través de SSE

    Ahora, abre una nueva ventana de terminal y navega hasta el directorio del proyecto. Úsalo create-react-apppara generar una aplicación React.

    1. npx create-react-app sse-client

    Navegue hasta el directorio de cliente recién creado:

    1. cd sse-client

    Ejecute la aplicación cliente:

    1. npm start

    Esto debería abrir una nueva ventana del navegador con tu nueva aplicación React. Esto completa la configuración de las dependencias para el frontend.

    Para darle estilo, abre el App.cssarchivo en tu editor de código y modifica el contenido con las siguientes líneas de código:

    cliente sse/src/App.css

    body {  color: #555;  font-size: 25px;  line-height: 1.5;  margin: 0 auto;  max-width: 50em;  padding: 4em 1em;}.stats-table {  border-collapse: collapse;  text-align: center;  width: 100%;}.stats-table tbody tr:hover {  background-color: #f5f5f5;}

    A continuación, abre el App.jsarchivo en tu editor de código y modifica el contenido con las siguientes líneas de código:

    cliente sse/src/App.js

    import React, { useState, useEffect } from 'react';import './App.css';function App() {  const [ facts, setFacts ] = useState([]);  const [ listening, setListening ] = useState(false);  useEffect( () = {    if (!listening) {      const events = new EventSource('http://localhost:3001/events');      events.onmessage = (event) = {        const parsedData = JSON.parse(event.data);        setFacts((facts) = facts.concat(parsedData));      };      setListening(true);    }  }, [listening, facts]);  return (    table className="stats-table"      thead        tr          thFact/th          thSource/th        /tr      /thead      tbody        {          facts.map((fact, i) =            tr key={i}              td{fact.info}/td              td{fact.source}/td            /tr          )        }      /tbody    /table  );}export default App;

    El useEffectargumento de la función contiene las partes importantes: un EventSourceobjeto con el /eventspunto final y un onmessagemétodo donde datase analiza la propiedad del evento.

    A diferencia de la cURLrespuesta, ahora tienes el evento como un objeto. Ahora puedes tomar la datapropiedad y analizarla, lo que te dará como resultado un objeto JSON válido.

    Finalmente, este código inserta el nuevo hecho en la lista de hechos y la tabla se vuelve a representar.

    Paso 4 – Prueba del frontend

    Ahora, intenta agregar un nuevo hecho.

    En una ventana de terminal, ejecute el siguiente comando:

    1. curl -X POST
    2. -H "Content-Type: application/json"
    3. -d '{"info": "Shark teeth are embedded in the gums rather than directly affixed to the jaw, and are constantly replaced throughout life.", "source": "https://en.wikipedia.org/wiki/Shark"}'
    4. -s http://localhost:3001/fact

    La POSTsolicitud agregó un nuevo dato y todos los clientes conectados deberían haberlo recibido. Si revisa la aplicación en el navegador, tendrá una nueva fila con esta información.

    Conclusión

    Este artículo sirvió como introducción a los eventos enviados por el servidor. En este artículo, creó una solución completa para el backend y el frontend para manejar la información en tiempo real que fluye del servidor al cliente.

    Los SSE fueron diseñados para el transporte unidireccional y basado en texto. Aquí se muestra el soporte actual para EventSourcelos navegadores .

    Continúa tu aprendizaje explorando todas las funciones disponibles paraEventSource dar me gusta retry.

    SUSCRÍBETE A NUESTRO BOLETÍN 
    No te pierdas de nuestro contenido ni de ninguna de nuestras guías para que puedas avanzar en los juegos que más te gustan.

    Deja una respuesta

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

    Subir

    Este sitio web utiliza cookies para mejorar tu experiencia mientras navegas por él. Este sitio web utiliza cookies para mejorar tu experiencia de usuario. Al continuar navegando, aceptas su uso. Mas informacion