Показать сообщение отдельно
  #2 (permalink)  
Старый 02.06.2023, 23:17
Аватар для ruslan_mart
Профессор
Отправить личное сообщение для ruslan_mart Посмотреть профиль Найти все сообщения от ruslan_mart
 
Регистрация: 30.04.2012
Сообщений: 3,018

Вероятно, с фронта просто нужно отправлять какой-то флажок, что мы сейчас вводим сообщение, причем отправлять раз в какой-то период, пока мы вводим

Соответственно, бэкенд по вебсокету принимает этот флаг и уведомляет также клиента на другой стороне, что идет печать

Но здесь важно подметить, что фронт не должен слать бэку сброс флага, если мы перестали печатать, так как есть много вариантов, что мы просто закрыли страницу и ничего отправляться не сможет

Клиент 1:
- Начинаем ввод сообщения
- Отправляем в вебсокету флаг
- Сохраняем где-то в переменную время, в которое было отправлено
- Если дальше печатаем, то делаем то же самое, только проверяем предыдущее время, что например, с текущим временем должна быть разница в 10 секунд (чтобы не перегружать сервер каждым вводом)

Сервер:
- В вебсокет приходит флаг, что клиент вводит сообщение
- Отправляем этот флаг "Клиенту 2"
- Запускаем setTimeout, что через 10 секунд мы должны автоматом отправить "Клиенту 2" флаг, что ввод сообщения "Клиентом 1" прекращен
- При этом, если "Клиент 1" отправил сообщение, то можно сбрасывать этот setTimeout
- Или если "Клиентом 1" новый флаг ввода сообщения пришел, то сбрасывать предыдущий setTimeout

Клиент 2:
- Подписан на веб-сокет
- Ожидает флаг, что "Клиент 1" вводит сообщение


<textarea id="message"></textarea>
<span id="result" hidden>Ваш собеседник печатает...</span>


const message = document.getElementById('message');
const result = document.getElementById('result');

const socket = new WebSocket('ws://localhost:8080');

socket.addEventListener('message', (event) => {
  const data = JSON.parse(event.data);

  result.hidden = !data.isStartedTyping;
});


let lastStartedTypingSend = null;

const SEND_TYPINING_MIN_INTERVAL = 15000; // 15 секунд

message.addEventListener('input', (event) => {
   const now = Date.now();
   
   if (lastStartedTypingSend === null || lastStartedTypingSend + SEND_TYPINING_MIN_INTERVAL < now) {
      lastStartedTypingSend = now;
     
      const payload = {
         isStartedTyping: true,
      };

      socket.send(JSON.stringify(payload));
   }
});


Сервер можно на NodeJS сделать, есть множество готовых решений для WS. Например, можно использовать этот пакет

Это первая идея, которая сходу пришла в голову. Уверен, что есть множество разных реализаций этой механики
Ответить с цитированием