27. Чат через long-polling, чтение POST

Цель этой главы, научиться делать чат на Node.JS. Для начала, наш чат будет достаточно простой, всего лишь каждый кто заходить по этому url — localhost:3000 автоматически попадает в комнату, в которой получает сообщения. Например я набираю что то в одном окне браузера и то что я набрал появляется и в другом окне браузера, в данном случае оба браузера на одном компьютере но могут быть и на разных краях света.

screenshot_27_01

Вот такой чат, просто обмен сообщениями. Мы будем делать его в начале без пользователей, без базы данных, без авторизации, такой вот простой, но качественно созданный чат. И так, поехали. Для начала как оно в общем будет устроено. Алгоритм общения с сервером, который изображен на этой схеме

screenshot_27_02

Называется «long polling», что в переводе длинные запросы. Он с одной стороны очень простой, с другой стороны в девяносто процентах задач, когда нужно общаться с сервером, он отлично подходит. Посмотрим на него повнимательней. Когда клиент хочет получать данные от сервера, то он отправляет на сервер XMLHttpRequest, самый обычный запрос, но не обычной является его обработка сервером. Сервер, получив такой запрос, не будет сразу на него отвечать, а просто оставит запрос подвисшим, дальше в будущем, как только появятся данные для клиента, сервер ответит на этот запрос, клиент получит ответ, какое то сообщение, обработает его выведет сообщение и сделает новый запрос на сервер, сервер опять, если данных нет то подождет, подождет, как только данные появятся, тут же ответит. Фактически получается, что клиент все время старается держать рабочее соединение к серверу, по которому, как только данные будут готовы, он их сразу же получит. Соответствующий код на стороне клиента, выглядит так

Есть форма, для отправки сообщений

И есть список, «messages», куда сообщения приходят

При submit формы, создается XMLHttpRequest и сообщение обычным порядком постится на сервер

Ну а для получения новых сообщений, как раз используется алгоритм long polling описанный ранее. Есть функция subscribe()

которая запускает XMLHttpRequest и говорит получи ка  данные с этого url — xhr.open(«GET», «/subscribe», true); Когда будет получен ответ с сервера, он показывается в  виде сообщения и заново вызывается функция subscribe();

то есть делается новый запрос. И так все это идет по кругу.

Исключение, если произошла ошибка или что то не так, в этом случае мы subscribe() тоже заново отправим, но с небольшой задержкой, чтобы не завалить сервер —

Обратим внимание, что этот код реализует алгоритм long polling, он не привязан к какому то конкретному чату, это просто код подписки на сообщение сервера, его можно расширять, можно добавлять различные каналы получения сообщений и так далее, но сейчас пока мы этого делать не будем, а перейдем к Node.JS.

Для серверной части у нас так же есть не большая заготовка

которая представляет собой Http server, умеющий отдавать index.html в качестве главной страницы. Так же будут два url, вот такой — ‘/subscribe’, для подписки на сообщение, и такой — ‘/publish’, для отправки сообщений. Они в точности такие же, какие вы видели в index.html.

Начнем реализацию с подписки. Функция subscribe, со странички index.html, будет отправлять длинные запросы именно на url ‘/subscribe’. Клиент, который отправил запрос на subscribe, с одной стороны не должен получить ответ прямо сейчас, с другой стороны мы должны запомнить, что он обратился за данными, чтобы потом, когда данные появятся, ему их передать. Для решения этой задачи создадим специальный объект который будет называться «chat» и «chat.subscribe» будет запоминать что пришел клиент, для этого мы передадим ему объекты req и res — «chat.subscribe(req, res)». Ну а «chat.publish(«….»)» будет пересылать это сообщение всем клиентам которые сейчас есть. Описывать этот объект chat я буду в отдельном модуле который расположу в текущей директории.