Инструменты для создания приложений реального времени в браузере постоянно улучшаются. Запуск node.js на сервере в сочетании с библиотеками, такими как socket.io, чрезвычайно упрощает реализацию серверного push-уведомлений и событийной коммуникации между клиентами. Соедините это с Twilio Client для голосовой связи в браузере, и у вас будет невероятно мощная платформа для обеспечения коммуникации между пользователями вашего приложения.
В этом руководстве мы рассмотрим пример приложения, позволяющего осуществлять парное (или групповое!) программирование в браузере. Проверьте его в действии здесь! Вы сможете общаться голосом с другими разработчиками, а изменения будут волшебным образом передаваться в реальном времени из их редактора в ваш. Ознакомьтесь с полным исходным кодом на GitHub, чтобы увидеть, как все это работает.
Парное программирование в режиме реального времени с распределенной командой вполне возможно с некоторыми из технологий, которые мы рассмотрим сегодня. Давайте пройдемся по списку необходимых компонентов для этого хака:
— node.js на сервере
— Официальный модуль twilio для node, доступный на npm
— SDK Twilio Client для JavaScript (для браузера)
— socket.io (как сервер, так и клиент)
— Express для маршрутизации HTTP-запросов и предоставления ответов
— Редактор кода Ace (браузер)
— AppFog (платформа как услуга для хостинга)
Приложение достаточно большое, поэтому мы сосредоточимся только на самых важных участках кода как на стороне клиента, так и на стороне сервера. Давайте начнем с того, что происходит в браузере.
Разметка единственной страницы приложения не очень сложна, но я хотел бы отметить несколько ключевых моментов:
В строке № 4 мы включаем компонент библиотеки socket.io для браузера. Он будет обрабатывать связь через веб-сокеты или HTTP long polling с нашей программой node.js, работающей на сервере. Глядя на тег script, вы можете подумать, что «socket.io/socket.io.js» находится в каталоге статического контента нашего веб-приложения, но на самом деле он генерируется динамически socket.io. Это обрабатывается автоматически – вам не нужно ничего дополнительно настраивать.
На следующей строке мы загружаем JavaScript для редактора Ace с rawgithub.com, что является удобным сервисом для быстрого доступа к необработанным файлам из репозитория GitHub. Также возможно скачать и обслуживать этот JavaScript локально.
Далее, в строке № 6, мы загружаем SDK Twilio Client для JavaScript с сервера статического контента, предоставленного Twilio. Он включается с помощью URL-адреса, относительного к протоколу, поэтому его можно обслуживать как по HTTP, так и по HTTPS. Сразу после этого мы загружаем jQuery 2.0 с Google CDN. Теперь все сторонние зависимости JavaScript, которые нам нужны, загружены для страницы.
Разметка пользовательского интерфейса страницы довольно проста – несколько div и пустой неупорядоченный список. Большую часть этого мы будем заполнять с помощью JavaScript позже. В строке № 20 мы загружаем JavaScript, который фактически будет управлять нашим приложением. CSS для страницы устанавливает полностраничный двухколоночный макет для нашего редактора и списка подключенных клиентов.
Давайте погрузимся в JavaScript, который обеспечивает работу клиентского приложения, которое можно найти здесь.
Сначала мы настраиваем редактор Ace с плагином подсветки синтаксиса JavaScript:
Затем мы создаем наш клиентский интерфейс socket.io и слушаем обновления от других клиентов:
Обратите внимание, что мы устанавливаем булевый флаг каждый раз, когда получаем новое обновление с сервера, чтобы указать, что редактор был обновлен нашим собственным кодом на стороне клиента. Мы делаем это, чтобы предотвратить срабатывание события «change» редактора каждый раз, когда с сервера поступает обновление, что затем вызывало бы отправку обновлений всем другим клиентам, вызывая нежелательное бесконечное поведение обмена сообщениями. Вроде того, как ваша мама научилась отправлять текстовые сообщения.
В обработчике события document ready мы устанавливаем прослушиватель для объекта редактора, который срабатывает каждый раз, когда пользователь обновляет содержимое текстового редактора:
Если изменение было инициировано вводом пользователя, мы немедленно публикуем сообщение в нашем сокете, указывающее, что у нас есть изменения в редакторе для публикации всем клиентам. Это обновляет все подключенные клиенты почти мгновенно.
Эти фрагменты кода обеспечивают обновления редактора текста в реальном времени, но как насчет голосового чата и событий присутствия при входе новых пользователей? Здесь мы начинаем использовать SDK Twilio Client для JavaScript. В событии document ready мы инициализируем программный телефон нашего браузера, объект «Twilio.Device», с помощью сгенерированного сервером токена возможностей:
Мы отправляем Ajax-запрос на сервер с помощью jQuery для получения этого токена возможностей, используя имя пользователя, которое пользователь ввел нам при «prompt()» во время загрузки страницы. В обработчике успеха мы инициализируем наш Twilio.Device, и мы готовы совершать исходящие звонки в голосовую конференцию, настроенную для этого редактора.
Также внутри функции обработчика успеха мы регистрируем прослушиватель для события присутствия, запускаемого Twilio Client. Это событие срабатывает один раз для каждого подключенного клиента при их подключении или отключении. В нашем случае мы будем добавлять (или удалять) их из неупорядоченного списка подключенных клиентов, просто чтобы показать, кто доступен (потенциально) для чата:
Чтобы подключиться к конференц-связи редактора, мы вызываем Twilio.Device.connect(). Чтобы выйти из конференции (повесить трубку), мы вызываем Twilio.Device.disconnectAll().
На этом заканчиваются основные моменты клиентской части нашего приложения. Мы распространяем изменения в редакторе текста с помощью socket.io и управляем присутствием и голосовым чатом через Twilio Client. Давайте посмотрим на серверную часть нашего приложения.
Наше серверное приложение представляет собой один файл JavaScript, который обрабатывает HTTP-запросы и обмен данными по сокету с клиентом. Давайте рассмотрим наиболее интересные моменты, исключив объявление зависимостей и стандартный код конфигурации Express.
Возможно, вы помните, что на стороне клиента мы сделали Ajax-запрос на получение токена возможностей, который позволяет нашему Twilio.Device совершать исходящие звонки (и подключаться к конференции). Это обработчик Express для этого маршрута:
Мы используем модуль twilio для node для создания токена возможностей с двумя частями данных – идентификатором клиента (это похоже на входящий номер телефона клиента) и идентификатором приложения TwiML (это идентификатор приложения TwiML, которое предоставляет инструкции TwiML для исходящего звонка из браузера). TwiML, используемый для совершения исходящего звонка, выглядит следующим образом:
Он использует преобразование текста в речь, чтобы объявить пользователю, что он присоединяется к конференции, а затем переводит пользователя в конференцию с другими пользователями редактора, подключенными в данный момент.
Обратите внимание, что конструктор токена возможностей должен иметь доступ к вашему учетному SID Twilio и токену аутентификации; по умолчанию библиотека node ищет эти значения в переменных окружения, доступных программно по адресам «process.env.TWILIO_ACCOUNT_SID» и «process.env.TWILIO_AUTH_TOKEN». Хранение учетных данных вашей учетной записи Twilio в переменных окружения является хорошей практикой безопасности, чтобы они случайно не попали в систему контроля версий.
Теперь мы готовы рассмотреть реализацию socket.io на сервере. socket.io сначала необходимо подключить к HTTP-серверу. Затем вы сможете слушать события и отправлять их:
В этом приложении каждый раз, когда сообщение принимается от клиента, мы передаем его обратно всем подключенным клиентам. Способ достижения этого — функция «socket.broadcast.emit()» — она отправит сообщение всем подключенным клиентам с новым значением редактора в браузере.
В демонстрации в реальном времени я развернул приложение на PaaS AppFog. Как и многие PaaS-сервисы node.js, AppFog пока не поддерживает веб-сокеты. К счастью, socket.io позволяет нам очень легко перейти к HTTP-опросу, который я настраиваю здесь на сервере. Если ваш PaaS поддерживает веб-сокеты (или вы работаете на выделенном сервере или VPS), вы можете пропустить эту настройку.
За несколько сотен строк кода мы создали приложение с редактором кода и чатом в реальном времени, которое с некоторыми улучшениями может позволить распределенным командам эффективно работать вместе. Мы можем сделать это, потому что инструменты для совместной работы в реальном времени значительно развились, и у нас есть серверная и клиентская платформы, построенные с нуля для поддержки событийно-ориентированной коммуникации. Я надеюсь, что вы сможете исследовать этот тип взаимодействия в своих приложениях уже очень скоро!