Превратите базовый c опрос в длинный опрос - PullRequest
3 голосов
/ 08 января 2020

Я разрабатываю приложение для чата и до сих пор опрашиваю свой сервер на наличие сообщений каждые две секунды. Чтобы сделать чат более мгновенным, я бы хотел провести длинный опрос. Я пытаюсь реализовать это JS .info Guide для него, но я не продолжаю достигать цели, которую намереваюсь достичь. Кто-нибудь может указать на это в моем случае?

У меня есть специальный хук для реакции в реакции, который пока является базовым c.

К вашему сведению: я новичок и сейчас не буду использовать WS или Socket.io. Это слишком много для меня на данный момент.

Заранее спасибо!

export default function useGetChatMessages(_id) {
  const [chatMessages, setChatMessages] = React.useState([]);

  React.useEffect(() => {
    const interval = setInterval(() => {
      getChatMessages(_id).then(fetchedChatMessages => {
        setChatMessages(fetchedChatMessages);
      });
    }, 2000);
    return () => clearInterval(interval);
  }, [_id]);

  return chatMessages;
}

Это моя серверная функция с express. Я думаю, что это должно быть реализовано здесь, а не в моем хуке

router.get('/:id/messages', async (request, response) => {
  try {
    const chat = await Chat.findById(request.params.id);
    response.json(chat.messages);
  } catch (error) {
    console.log(error);
    response.status(500).json({ message: error.message });
  }
});

Ответы [ 2 ]

5 голосов
/ 08 января 2020

Длинный опрос - это в основном способ держать HTTP-соединение открытым, поэтому вам нужно реализовать это на стороне сервера, ваш интерфейс не сможет контролировать, что сервер делает с запросом.

В качестве стороны обратите внимание, что длительный опрос, как правило, намного сложнее для сервера, чем для веб-сокетов, и, честно говоря, было бы лучше потратить время на подключение к веб-сокету, так как настройка базового c ws-сервера не так сложна, если вы используете библиотеку, такую ​​как сокет. io

Редактировать: так же, как примечание semanti c, Длинный опрос - это управляемый событиями способ отправки сервером ответа клиенту без отправки клиентом специального c запроса с запросом этих данных, тогда как обычный опрос - это просто отправка запросов с заданным интервалом c (похоже, вы уже знаете это, потому что упомянули, что хотите сделать опрос более быстрым).

Если вы заинтересованы в улучшении настроек обычного опроса взгляните на другой ответ.

0 голосов
/ 08 января 2020

Длинный опрос также требует изменений в бэкэнде. Таким образом, предполагая, что вы не можете изменить код на стороне сервера, вы все равно можете реализовать более полный опрос basi c http.
Чтобы выполнить опрос basi c http, вы должны вызывать свой API после последнего успешного вызова, поэтому Вы убедитесь, что только один вызов API ставится в очередь.

Я также добавил грубый Экспоненциальный откат , чтобы лучше обрабатывать ошибки. Это предотвратит перегрузку вашего интерфейса вашим сервером, если у вас возникнут проблемы с бэкендом (например, сбой).

Адаптация вашего кода будет выглядеть так:

export default function useGetChatMessages(_id) {
  const [chatMessages, setChatMessages] = React.useState([]);

  React.useEffect(() => {
    let delay = 1000;
    let timeout = null;

    const updateChat = () => {
      getChatMessages(_id).then(fetchedChatMessages => {
        // you must also consider passing a timestamp to the API call
        // so you only fetch the latest messages, instead of all of them every time
        // your state update would look like this:
        // setChatMessages((messages) => [...messages, fetchedChatMessages]);
        setChatMessages(fetchedChatMessages);
        // reset the delay in case an error has happened and changed it.
        delay = 1000;
        // now call the API again after 1 second
        timeout = setTimeout(updateChat, delay);
      }).catch(error => {
        // exponential backoff here.
        // 1 - the first error will call the API after 2sec
        // 2 - the second error will call the API after 4 sec
        // 3 - the third error will call the API after 8 sec
        // and so on
        console.error("Could not update chat. waiting a bit...", error);
        delay = delay * 2;
        timeout = setTimeout(updateChat, delay);
      });
    }

    return () => timeout && clearTimeout(timeout)

  }, [_id]);

  return chatMessages;
}
...