В этом блоге мы узнаем, что такое события, отправленные сервером, и создадим окно чата для прямой трансляции с помощью Node.

Что такое события, отправленные сервером

События, отправленные сервером, являются одним из методов связи между сервером и клиентом, который позволяет клиентскому приложению получать обновления после установления соединения с сервером.

Чем события, отправленные сервером, отличаются от веб-сокетов?

WebSocket — это протокол связи, который обеспечивает соединение между клиентским компьютером и сервером, что позволяет отправлять и получать информацию между ними. Этот протокол используется в сценариях, когда клиенту необходимо получать мгновенные обновления с сервера. Некоторыми примерами, где это можно использовать, являются чат-приложения, обновления результатов в реальном времени и т. д.
В случае событий, отправленных сервером, клиент сможет получать данные с сервера только после установления соединения. Этот подход можно использовать в тех случаях, когда вам нужны только обновления с сервера и вам не нужно отправлять постоянную информацию от клиента. Вы можете использовать события, отправленные сервером, в таких сценариях, как обновления результатов в реальном времени, лента новостей, опросы Twitter / Instagram Likes и т. д.

Как работают события, отправленные сервером?

На стороне сервера мы отправляем данные клиенту в виде потоков событий. Поток событий — это последовательность событий, выполняемых последовательно. Для отправки потоков событий мы отправляем данные ответа в типе содержимого text/event-stream. На стороне сервера мы добавим наблюдатель/интервал, который получает данные об изменении данных в случае наблюдателя и через определенный интервал времени в случае интервалов. Всякий раз, когда выполняется наблюдатель/интервал, мы отправляем поток событий клиенту.
На стороне клиента мы используем веб-API под названием EventSource. Этот объект используется для установления соединения с сервером, получения потоков событий с сервера и использования его для отображения данных в реальном времени. Этот объект заботится об установлении соединения с сервером, получении потоковых данных и закрытии соединения, когда клиент или сервер выходят из сеанса.

Реализация событий, отправленных сервером

Чтобы понять эту реализацию, мы реализуем чат YouTube Live, где пользователи могут комментировать видео в прямом эфире и получать обновления комментариев к видео в реальном времени.

Клиентская сторона

Создайте файл JavaScript и добавьте приведенный ниже фрагмент кода. Этот фрагмент кода инициализирует соединение и отслеживает данные с сервера.

const eventSource = new EventSource('https://localhost:5000/get-live-feed');

/**
 * Method to convey that the connection with server is established.
 */
eventSource.onopen = () => {
  console.log("connected");
};

/**
 * Method to receive
 * response data from the server.
 */
eventSource.onmessage = (event) => {
  updateMessage(event.data);
};

/**
 * Method to convey connection failures.
 */
eventSource.onerror = function () {
  console.log("Server closed connection");
  eventSource.close();
};

На стороне сервера

Мы будем использовать экспресс-библиотеку для работы с API. Ниже будет ваш метод API.

app.get("/get-live-feed", (req, res) => {
  res.writeHead(200, {
    "Content-Type": "text/event-stream",
    "Cache-Control": "no-cache",
    "Access-Control-Allow-Origin": "*",
    "Connection": "keep-alive",
  });

  /**
   * Logic for watcher start
   */

  

   /**
   * Logic for watcher end
   */

  /**
   * Log message when user exits
   * the session and close the stream.
   */
  res.on("close", () => {
    console.log("connection close");
    changeStream.close();
    res.end();
  });
});

Чтобы объект EventSource получил данные, нам нужно отправить следующие заголовки ответа.

«Content-Type»: «text/event-stream»
«Cache-Control»: «no-cache»
«Access-Control-Allow-Origin»: «*»
« Соединение»: «поддерживать

Используйте метод write(), чтобы добавить данные ответа, которые будут отправлены клиенту. EventSource ожидает, что данные будут в формате «данные:» + {{yourData}} + «\n\n». Используйте метод flush(), чтобы отправить текущие данные клиенту, а не закрывать сеанс. Закрыть сеанс сервера при выходе из сеанса клиента.

/**
 * Watch the message collection for
 * Changes and send the data to the
 * client.
 */
const msgCollection = db.collection("message");
let changeStream = msgCollection.watch();
changeStream.on("change", (change) => {
  if (change.operationType === "insert") {
    const messageDetails = change.fullDocument;
    res.write("data: " + JSON.stringify(messageDetails) + "\n\n");
    res.flush();
  }
});

Мы используем приведенную выше логику для получения данных из коллекции сообщений. Коллекция сообщений содержит все данные живого чата. У нас есть POST API
/add-message, который добавляет пользовательские данные в коллекцию сообщений. Всякий раз, когда коллекция сообщений обновляется, мы используем метод watch() для получения обновлений коллекции. При получении действия вставки мы отправляем эти данные всем подключенным клиентам.

На стороне клиента мы анализируем эти данные и добавляем их в DOM, как показано ниже.

function updateMessage(data) {
  const { name, message } = JSON.parse(data);
  const chats = document.getElementById("chat-data");
  const chat = `<p><b>${name}: </b>${message}</p>`;
  const chatres = document.createRange().createContextualFragment(chat);
  chats.appendChild(chatres);
  document
    .querySelector(".chat-content")
    .scrollTo(0, document.querySelector(".chat-content").scrollHeight);
}

Демо: https://maheshudvag.github.io/Youtube-Live-Chat/
Код: https://github.com/MaheshUdvag/Youtube-Live-Chat

Если вам понравилась эта статья, подпишитесь на меня в @maheshudvag, чтобы узнать больше подобного контента.

Свяжитесь со мной

Linkedln: https://in.linkedin.com/in/mahesh-udvag-a0a834129
Instagram: maheshudvag