Как разработать приложение для большого чата с Socket.io и Node.js

Я работаю с Socket.io за последние несколько месяцев, разрабатывая довольно сложное приложение для чата с чатами, ногами/запретами/модераторами/друзьями/и т.д.

В ходе разработки я несколько раз переписал приложение, и я все еще сражаюсь с моим кодом.

Мне очень нравится JavaScript, но мне очень сложно поддерживать приложение по мере его роста. Я прочитал огромное количество "учебников" о том, как писать чат-приложения, но все они охватывают только самые основные аспекты. То же самое касается всех приложений на GitHub и даже большинства чат-приложений, которые я нашел в Интернете (большинство из них - просто простой IM без какого-либо управления пользователями).

Некоторые примеры использования кажутся мне слишком смешными, например, ногами пользователя из комнаты.

  • Модератор нажимает на кнопку kick → выдает событие на сервер
  • сервер связывает имя пользователя с сокетом (или просто передается всем пользователям и фильтрует на стороне клиента) → выдавать ему нокаутированное событие
  • пользователь выдает событие выхода на сервер и также выводит сообщение о том, что его ударили (выход из системы - это только моя реализация наказания).
  • пользователь удаляется из списка пользователей чата → издает текущий список пользователей всем пользователям в комнате

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

Там есть еще одна проблема на стороне клиента, где я должен прослушивать события сокета в нескольких местах, поэтому у меня должен быть какой-то один глобальный объект сокета singleton и перехватывать прослушиватели событий в нескольких местах.

Я делаю что-то не так, или этот обратный вызов - результат работы с веб-сайтами без возможности его использования?

Есть ли способы упростить разработку приложений? Например, альтернативные технологии для Socket.io? До сих пор я только нашел NowJS, который имеет последнее завершение 5 месяцев назад, и meteor, что действительно здорово, но, глядя на веб-сайт, он действительно не выглядит стабильным.

Ответ 1

Просто используйте promises мой друг. jQuery использует их, но на стороне nodejs вы можете использовать библиотеку q. Не записывайте асинхронный код без них! Они немного привыкают, но как только вы находитесь в мышлении, асинхронный код - легкий ветерок.

Существуют также библиотеки, такие как async, которые предоставляют вам служебные функции вокруг кода обратного вызова. Но не позволяйте популярности обмануть вас. promises сладки.

Для асинхронного тестирования кода вам не нужно идти намного дальше nodeunit, который дает вам простую функцию done(), которую вы можете вызвать, когда ваш тест поэтому он может работать до тех пор, пока вам нравится.

Ответ 2

Ого, позвольте разбить это на реальные проблемы, поскольку я не вижу много определенных:

Извлечение пользователя из комнаты:

  • модератор нажимает кнопку "Удалить" (emit должен содержать идентификатор комнаты и идентификатор пользователя).
  • код сервера удаляет пользователя из объекта "Комната" и отправляет сообщение каждому пользователю в комнате, в котором был удален пользовательский идентификатор. Если раньше у вас было соединение с пользователем (roomID), код сервера для этого выглядел бы следующим образом:

    sio.sockets.to(roomID).emit('kicked', { userID: uid });
    

Это все. В клиентском коде вы должны получить это событие "kicked" и иметь такой код:

if (data.removedUserID == myUserID)
    alert('You have been kicked by moderator');
else
    removeUserFromList(userID);

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

Я должен слушать события сокета в нескольких местах

Почему? Что означает "несколько мест"?

Есть ли способы упростить разработку приложений?

  • Не просто погружайтесь в код. Подумайте, как люди будут общаться напрямую. Клиенты - это люди, отправляющие сообщения, сервер - почта. Переведите логику в коде позже.
  • Убедитесь, что сервер является единственным в управлении, а клиенты предоставляют команды и отображают состояние без какой-либо логики.

Я разработал многопользовательскую игру 4000 loc, где чат - лишь небольшая часть. У меня около 60 000 пользователей, играющих его каждый день. Все это простой код socket.io с некоторыми Express/EJS, чтобы получить экраны, и я не могу себе представить, чтобы это стало проще. Особенно не используя какую-то "магическую" библиотеку, которая скроет от меня всю коммуникацию и обязательно представит ей собственный набор ошибок, ожидающих обнаружения и исправления.

Ответ 3

Раскрытие информации: Я разработчик scoop.

У меня была более или менее та же проблема, и она сводится к обычной пирамиде обратного вызова, которая может быть решена многими библиотеками (их десятки, просто посмотрите.

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

Это простая библиотека, которая пытается помочь как все другие async libs, смоделированные после шага с каким-то личным вкусом. Взгляните на примеры, они могут соответствовать вашим потребностям.

Ответ 4

Вы также можете взглянуть на derby.js. Это структура, очень похожая на meteor, но построена на всех "лакомствах" node.js, таких как npm, socket.io, Express и т.д. Derby включает мощный механизм синхронизации данных под названием Racer, который автоматически синхронизирует данные между браузерами, серверами и базой данных. У них даже есть основной пример чата.

Meteor использует много своих технологий (волокна, собственный менеджер пакетов). Как метеорное дерби все еще находится в альфа-фазе, но в последний раз получило большую привлекательность. Недавно Airbnb объявила, что рассмотрит дерби для будущих реализаций.

Дополнительная информация:

Ответ 5

Трудно ответить на ваш вопрос, но я могу заверить вас, что я чувствую вашу боль... Даже без node.js обратные вызовы могут получить волосатые довольно быстро, а асинхронное тестирование действительно сложно сделать. Наверное, я должен сказать: трудно преуспеть, но это может звучать так, как будто я знаю, как сделать это легко, а я нет. Фоновая проблема заключается в том, что асинхронная разработка сложна, так же как и параллельное программирование.

Я не думаю, что другая библиотека websocket поможет вам или даже полностью избегать websockets. Что может помочь вам использовать несколько трюков. Энди Рэй выше предлагает promises; Я не использовал их широко, но стоит попробовать.

Самодиагностика - ваш друг. JavaScript - это динамический язык без системы типа, которая стоит его соли и которая маскирует нулевые объекты; только огромная батарея автоматических тестов может обеспечить качество. Но, как вы говорите, тестирование может быть очень трудным.

Еще один трюк: примените ваше приложение как сумасшедшее. Отправляйте события и проверяйте их в своих тестах. Мы создали классный набор тестов вокруг браузера без браузера (PhantomJS), где мы проверяем с помощью JavaScript, что клиент отправляет правильные события; его трудно отладить, но он работает.

Конечно, обычные советы по дизайну помогают: KISS, YAGNI и т.д., но я не буду оскорблять ваш интеллект ими. Удачи.