Расширение websockets
Расширение WebSockets позволяет легко осуществлять двустороннюю коммуникацию с серверами WebSockets непосредственно из HTML. Это заменяет экспериментальное атрибут hx-ws в предыдущих версиях htmx. Для помощи в миграции из более ранних версий, см. руководство по миграции внизу этой страницы.
Используйте следующие атрибуты для настройки поведения WebSockets:
-
ws-connect="<url>"илиws-connect="<prefix>:<url>"- URL для установления подключенияWebSocket. - Префиксы
wsилиwssмогут быть указаны необязательно. Если они не указаны, HTMX по умолчанию добавляет схему, хост и порт расположения, чтобы браузеры отправляли куки через websockets. -
ws-send- отправляет сообщение ближайшему websocket, в зависимости от значения триггера для элемента (либо естественного события, либо события, указанного в [hx-trigger])
Установка
<script src="https://unpkg.com/htmx.org/dist/ext/ws.js"></script>
Использование
<div hx-ext="ws" ws-connect="/chatroom">
<div id="notifications"></div>
<div id="chat_room">
...
</div>
<form id="form" ws-send>
<input name="chat_message">
</form>
</div>
Настройка
Расширение WebSockets поддерживает два параметра настройки:
-
createWebSocket- функция-фабрика, которая может использоваться для создания экземпляров WebSocket. Должна быть функцией, возвращающей объектWebSocket -
wsBinaryType- строковое значение, определяющее свойствоbinaryTypeсокета. Значение по умолчаниюblob
Приём сообщений от WebSocket
В примере выше устанавливается WebSocket для конечной точки /chatroom. Содержимое, отправленное через websocket, будет обработано как HTML и заменено свойством id, используя ту же логику, что и при обмене вне зоны видимости.
Таким образом, если вы хотите изменить метод обмена (например, добавить содержимое в конец элемента или делегировать обмен расширению), вам необходимо указать это в теле сообщения, отправленном сервером.
<!-- will be interpreted as hx-swap-oob="true" by default -->
<form id="form">
...
</form>
<!-- will be appended to #notifications div -->
<div id="notifications" hx-swap-oob="beforeend">
New message received
</div>
<!-- will be swapped using an extension -->
<div id="chat_room" hx-swap-oob="morphdom">
....
</div>
Отправка сообщений в WebSocket
В примере выше форма использует атрибут ws-send для указания того, что при отправке формы значения формы должны быть сериализованы как JSON и отправлены ближайшему включающему WebSocket, в данном случае конечной точке /chatroom.
Сериализованные значения будут включать поле HEADERS, содержащее заголовки, обычно отправляемые с запросом htmx.
Автоматическое подключение
Если WebSocket неожиданно закрывается из-за Abnormal Closure, Service Restart или Try Again Later, это расширение будет пытаться переподключиться до тех пор, пока подключение не будет восстановлено.
По умолчанию расширение использует алгоритм экспоненциального замедления с полным джиттером алгоритм экспоненциального замедления, который выбирает случайное время ожидания повторной попытки, экспоненциально возрастающее со временем. Вы можете использовать другой алгоритм, записав его в htmx.config.wsReconnectDelay. Эта функция принимает единственный параметр — количество попыток и возвращает время (в миллисекундах) ожидания перед следующей попыткой.
// example reconnect delay that you shouldn't use because
// it's not as good as the algorithm that's already in place
htmx.config.wsReconnectDelay = function (retryCount) {
return retryCount * 1000 // return value in milliseconds
}
Расширение также реализует простую механизм очереди, который сохраняет сообщения в памяти, когда сокет не находится в состоянии OPEN, и отправляет их после восстановления соединения.
События
Расширение WebSockets предоставляет набор событий, позволяющих наблюдать и настраивать его поведение.
Событие - htmx:wsConnecting
Это событие срабатывает при попытке подключения к конечной точке WebSocket.
Подробности
-
detail.event.type- тип события ('connecting')
Событие - htmx:wsOpen
Это событие срабатывает при успешном подключении к конечной точке WebSocket.
Подробности
-
detail.elt- элемент, содержащий сокет (элемент с атрибутомws-connect) -
detail.event- исходное событие сокета -
detail.socketWrapper- оболочка объекта сокета
Событие - htmx:wsClose
Это событие срабатывает при нормальном закрытии подключения к конечной точке WebSocket. Вы можете проверить, было ли событие вызвано ошибкой, проверив свойство detail.event.
Подробности
-
detail.elt- элемент, содержащий сокет (элемент с атрибутомws-connect) -
detail.event- исходное событие сокета -
detail.socketWrapper- оболочка объекта сокета
Событие - htmx:wsError
Это событие срабатывает при возникновении события onerror на сокете.
Подробности
-
detail.elt- элемент, содержащий сокет (элемент с атрибутомws-connect) -
detail.error- объект ошибки -
detail.socketWrapper- оболочка объекта сокета
Событие - htmx:wsBeforeMessage
Это событие срабатывает при получении сообщения сокетом, аналогично событию htmx:beforeOnLoad. Это событие срабатывает до обработки любого содержимого.
Если событие отменено, дальнейшая обработка не будет выполнена.
-
detail.elt- элемент, содержащий сокет (элемент с атрибутомws-connect) -
detail.message- исходное содержимое сообщения -
detail.socketWrapper- оболочка объекта сокета
Событие - htmx:wsAfterMessage
Это событие срабатывает после полной обработки сообщения htmx и завершения всех изменений, аналогично событию htmx:afterOnLoad.
Отмена этого события не имеет эффекта.
-
detail.elt- элемент, содержащий сокет (элемент с атрибутомws-connect) -
detail.message- исходное содержимое сообщения -
detail.socketWrapper- оболочка объекта сокета
Событие - htmx:wsConfigSend
Это событие срабатывает при подготовке к отправке сообщения из элемента ws-send. Аналогично событию htmx:configRequest, оно позволяет модифицировать сообщение перед отправкой.
Если событие отменено, дальнейшая обработка не будет выполнена, и сообщения не будут отправлены.
Подробности
-
detail.parameters- параметры, которые будут отправлены в запросе -
detail.unfilteredParameters- параметры, найденные до фильтрации с помощьюhx-select -
detail.headers- заголовки запроса. Будут добавлены в тело в свойствоHEADERS, если не ложны -
detail.errors- ошибки валидации. Предотвратит отправку и вызовет событиеhtmx:validation:halted, если не пусто -
detail.triggeringEvent- событие, которое вызвало отправку -
detail.messageBody- исходное тело сообщения, которое будет отправлено в сокет. Неопределено, может быть установлено в значение любого типа, поддерживаемого WebSockets. Если установлено, переопределит стандартную сериализацию JSON. Полезно, если вы хотите использовать другой формат, например, XML или MessagePack -
detail.elt- элемент, который инициировал отправку (элемент с атрибутомws-send) -
detail.socketWrapper- оболочка объекта сокета
Событие - htmx:wsBeforeSend
Это событие срабатывает непосредственно перед отправкой сообщения. Это включает сообщения из очереди. Сообщение не может быть изменено на этом этапе.
Если событие отменено, сообщение будет удалено из очереди и не будет отправлено.
Подробности
-
detail.elt- элемент, который инициировал запрос (элемент с атрибутомws-connect) -
detail.message- исходное содержимое сообщения -
detail.socketWrapper- оболочка объекта сокета
Событие - htmx:wsAfterSend
Это событие срабатывает сразу после отправки сообщения. Это включает сообщения из очереди.
Отмена события не влияет на результат.
Подробности
-
detail.elt- элемент, который инициировал запрос (элемент с атрибутомws-connect) -
detail.message- исходное содержимое сообщения -
detail.socketWrapper- оболочка объекта сокета
Обёртка сокета
Вы можете заметить, что все события предоставляют свойство detail.socketWrapper. Эта обёртка содержит сам объект сокета и очередь сообщений. Она также инкапсулирует алгоритм переподключения. Она предоставляет несколько членов:
-
send(message, fromElt)- безопасно отправляет сообщение. Если сокет не открыт, сообщение будет сохранено в очереди и отправлено, когда сокет будет готов. -
sendImmediately(message, fromElt)- пытается отправить сообщение независимо от состояния сокета, минуя очередь. Может завершиться неудачей. -
queue- массив сообщений, ожидающих в очереди.
Эта обёртка может использоваться в обработчиках событий для мониторинга и манипулирования очередью (например, вы можете сбросить очередь при переподключении) и для отправки дополнительных сообщений (например, если вы хотите отправлять данные партиями). Параметр fromElt является необязательным и, при указании, вызовет соответствующие события websocket из указанного элемента, а именно htmx:wsBeforeSend и htmx:wsAfterSend события при отправке ваших сообщений.
Тестирование с демонстрационным сервером
Htmx включает демонстрационный сервер WebSockets, написанный на Node.js, который поможет вам увидеть WebSockets в действии и начать настройку своего кода WebSockets. Он находится в папке /test/ws-sse дистрибутива htmx. Обратитесь к файлу /test/ws-sse/README.md за инструкциями по запуску и использованию тестового сервера.
Миграция из предыдущих версий
Предыдущие версии htmx использовали встроенный тег hx-ws для реализации WebSockets. Этот код был перенесён в расширение вместо этого. Вот шаги, которые вам необходимо предпринять для миграции на эту версию:
| Старый атрибут | Новый атрибут | Комментарии |
|---|---|---|
hx-ws="" |
hx-ext="ws" |
Используйте атрибут hx-ext="ws" для установки расширения WebSockets в любой HTML-элемент. |
hx-ws="connect:<url>" |
ws-connect="<url>" |
Добавьте новый атрибут ws-connect к тегу, определяющему расширение, для указания URL веб-сервера WebSockets, который вы используете. |
hx-ws="send" |
ws-send="" |
Добавьте новый атрибут ws-send для обозначения всех дочерних форм, которые должны отправлять данные на ваш веб-сервер WebSockets |
Licensed under the Zero-Clause BSD License.
https://htmx.org/extensions/web-sockets/