Класс Client в библиотеке STOMP.js
является центральной точкой управления соединением с STOMP-брокером
поверх WebSocket. Через него выполняются:
Экземпляр Client инкапсулирует всю сетевую логику и
предоставляет высокоуровневый API для обмена сообщениями.
Базовое создание клиента:
import { Client } from '@stomp/stompjs';
const client = new Client();
После создания объект ещё не инициирует подключение. Соединение
начинается только после вызова метода activate().
Класс поддерживает передачу конфигурации напрямую в конструктор:
const client = new Client({
brokerURL: 'ws://localhost:15674/ws',
reconnectDelay: 5000
});
Такой подход позволяет сразу определить параметры подключения и поведение клиента.
Свойство brokerURL задаёт адрес
WebSocket-соединения.
Пример:
const client = new Client({
brokerURL: 'ws://localhost:8080/ws'
});
Поддерживаются:
ws://wss://Использование wss:// обязательно в production-среде при
HTTPS.
Пример защищённого подключения:
const client = new Client({
brokerURL: 'wss://example.com/ws'
});
Вместо brokerURL можно использовать фабрику
WebSocket.
Это особенно полезно:
Пример:
const client = new Client({
webSocketFactory: () => new WebSocket('ws://localhost:8080/ws')
});
SockJS обеспечивает fallback-транспорт при отсутствии полноценного WebSocket.
Пример:
import SockJS from 'sockjs-client';
import { Client } from '@stomp/stompjs';
const client = new Client({
webSocketFactory: () => new SockJS('http://localhost:8080/stomp')
});
В этом режиме brokerURL не используется.
Метод activate() инициирует подключение:
client.activate();
После вызова:
Клиент имеет внутреннее состояние жизненного цикла.
Основные этапы:
INACTIVE
ACTIVE
DEACTIVATING
Проверка активности:
console.log(client.active);
Если значение true, клиент активен либо находится в
процессе подключения.
onConnect вызывается после успешного STOMP CONNECT.
Пример:
client.onConn ect = (frame) => {
console.log('Connected');
};
Именно внутри onConnect обычно создаются подписки.
Типичный сценарий:
client.onConn ect = () => {
client.subscribe('/topic/messages', (message) => {
console.log(message.body);
});
};
client.activate();
Если создавать подписки до установки соединения, они не будут зарегистрированы брокером.
Срабатывает после DISCONNECT:
client.onDisconn ect = () => {
console.log('Disconnected');
};
Этот обработчик не вызывается при физическом разрыве WebSocket без STOMP DISCONNECT.
Позволяет обработать ERROR frame от брокера.
Пример:
client.onStompEr ror = (frame) => {
console.error('Broker error');
console.error(frame.headers['message']);
console.error(frame.body);
};
Наиболее частые причины:
Отлавливает ошибки WebSocket:
client.onWebSocketEr ror = (event) => {
console.error('WebSocket error', event);
};
Обычно возникает при:
Вызывается при закрытии соединения:
client.onWebSocketCl ose = (event) => {
console.log('Connection closed');
};
Через объект event можно получить:
event.code
event.reason
Параметр reconnectDelay включает reconnect.
Пример:
const client = new Client({
brokerURL: 'ws://localhost:15674/ws',
reconnectDelay: 5000
});
Если соединение потеряно, через 5 секунд начнётся повторная попытка подключения.
const client = new Client({
reconnectDelay: 0
});
В этом случае клиент не будет восстанавливать соединение автоматически.
Heartbeat используется для контроля активности соединения.
Настройка:
const client = new Client({
heartbeatIncoming: 4000,
heartbeatOutgoing: 4000
});
Интервал ожидания heartbeat от сервера.
Интервал отправки heartbeat серверу.
Если heartbeat не приходит в течение заданного времени:
Это позволяет обнаруживать “зависшие” TCP-соединения.
Для диагностики используется свойство debug.
Пример:
client.debug = (message) => {
console.log(message);
};
STOMP.js начинает выводить:
client.debug = () => {};
В production debug обычно отключают.
Метод publish отправляет сообщения брокеру.
Пример:
client.publish({
destination: '/queue/test',
body: 'Hello'
});
Можно передавать заголовки:
client.publish({
destination: '/queue/test',
headers: {
priority: '9'
},
body: 'Important message'
});
STOMP.js поддерживает бинарные данные.
Пример:
const bytes = new Uint8Array([1, 2, 3]);
client.publish({
destination: '/queue/binary',
binaryBody: bytes
});
Базовый пример:
const subscription = client.subscribe(
'/topic/chat',
(message) => {
console.log(message.body);
}
);
subscription.unsubscribe();
После отмены брокер прекращает доставку сообщений.
Поддерживаются режимы:
autoclientclient-individualПример:
client.subscribe(
'/queue/tasks',
(message) => {
console.log(message.body);
message.ack();
},
{
ack: 'client'
}
);
Подтверждение доставки:
message.ack();
После ACK брокер удаляет сообщение из очереди.
Отрицательное подтверждение:
message.nack();
В зависимости от брокера сообщение может:
STOMP поддерживает подтверждение операций.
Пример:
client.watchForReceipt('msg-1', () => {
console.log('Message delivered');
});
client.publish({
destination: '/queue/test',
body: 'Hello',
headers: {
receipt: 'msg-1'
}
});
Корректное завершение соединения:
await client.deactivate();
Метод:
Принудительное закрытие:
client.forceDisconnect();
Используется при:
Разница между методами:
| Метод | STOMP DISCONNECT | Закрытие WebSocket | Graceful shutdown |
|---|---|---|---|
| deactivate | Да | Да | Да |
| forceDisconnect | Нет | Да | Нет |
Позволяет передавать заголовки CONNECT frame.
Пример:
const client = new Client({
brokerURL: 'ws://localhost:15674/ws',
connectHeaders: {
login: 'admin',
passcode: 'admin'
}
});
Частый сценарий:
const client = new Client({
brokerURL: 'wss://example.com/ws',
connectHeaders: {
Authorization: 'Bearer token'
}
});
Асинхронная подготовка подключения.
Пример:
client.beforeConnect = async () => {
const token = await loadToken();
client.connectHeaders = {
Authorization: `Bearer ${token}`
};
};
Особенно важно при refresh JWT.
При мобильных сетях reconnect часто комбинируют с heartbeat:
const client = new Client({
reconnectDelay: 3000,
heartbeatIncoming: 10000,
heartbeatOutgoing: 10000
});
Это уменьшает количество ложных reconnect.
Параметр принудительно уничтожает WebSocket при ошибках связи.
Пример:
const client = new Client({
discardWebsocketOnCommFailure: true
});
Полезно при проблемах браузеров и proxy buffering.
Некоторые брокеры плохо работают с крупными STOMP frame.
Параметр:
const client = new Client({
splitLargeFrames: true
});
Размер частей frame:
const client = new Client({
splitLargeFrames: true,
maxWebSocketChunkSize: 8 * 1024
});
Позволяет видеть сырые STOMP frame.
const client = new Client({
logRawCommunication: true
});
Используется только для глубокой диагностики.
Некоторые серверы нарушают STOMP framing.
Настройка:
const client = new Client({
appendMissingNULLonIncoming: true
});
Используется как workaround для несовместимых брокеров.
Пример полноценной настройки:
const client = new Client({
brokerURL: 'wss://example.com/ws',
reconnectDelay: 5000,
heartbeatIncoming: 10000,
heartbeatOutgoing: 10000,
connectHeaders: {
Authorization: 'Bearer token'
},
debug: () => {}
});
После восстановления соединения подписки создаются заново.
Типичный подход:
client.onConn ect = () => {
client.subscribe('/topic/chat', handler);
client.subscribe('/queue/tasks', taskHandler);
};
onConnect вызывается после каждого reconnect.
Нельзя хранить старые subscription-объекты после reconnect:
let subscription;
client.onConn ect = () => {
subscription = client.subscribe('/topic/test', handler);
};
После reconnection предыдущая подписка уже невалидна.
Проблемный код:
client.onConn ect = () => {
initSubscriptions();
};
Если initSubscriptions() не очищает старые обработчики,
возможны:
При вызове:
await client.deactivate();
останавливаются:
Это важно при смене пользователя или logout.
Часто используется отдельный слой:
class SocketService {
constructor() {
this.client = new Client({
brokerURL: 'ws://localhost:8080/ws',
reconnectDelay: 5000
});
}
connect() {
this.client.activate();
}
disconnect() {
return this.client.deactivate();
}
}
Такой подход:
В React/Vue/Angular экземпляр Client обычно:
Создание множества клиентов одновременно приводит к:
После вызова activate() происходит следующая
последовательность:
WebSocket connect
↓
STOMP CONNECT
↓
CONNECTED frame
↓
onConnect
↓
SUBSCRIBE
↓
MESSAGE exchange
DISCONNECT
↓
Receipt ожидание
↓
Heartbeat stop
↓
WebSocket close
↓
INACTIVE
Ошибка:
client.subscribe('/topic/test', handler);
client.activate();
Подписка не будет зарегистрирована.
Ошибка:
client.activate();
client.activate();
Может привести к гонкам reconnect и нескольким WebSocket.
Проблемная конфигурация:
heartbeatIncoming: 1000
На нестабильных сетях это вызывает постоянные reconnect.
Если heartbeat отключён:
heartbeatIncoming: 0,
heartbeatOutgoing: 0
клиент может долго не замечать разрыв TCP-соединения.
Класс Client управляет:
Благодаря этому приложение работает с высокоуровневым API, не взаимодействуя напрямую с STOMP protocol frame.