Надёжная обработка ошибок в STOMP.js строится на нескольких уровнях: транспортный (WebSocket), протокольный (STOMP frames), уровень клиента (логика обработки сообщений) и уровень брокера (ошибки очередей и подписок). Игнорирование любого из этих уровней приводит к “тихим” сбоям, разрывам соединения и потере сообщений без явных признаков причины.
STOMP.js использует WebSocket как транспорт, поэтому любые проблемы соединения сначала проявляются именно здесь.
Основные точки обработки:
В STOMP.js за это отвечают события клиента:
import { Client } from '@stomp/stompjs';
const client = new Client({
brokerURL: 'ws://localhost:15674/ws',
onWebSocketError: (event) => {
console.error('WebSocket ошибка:', event);
},
onWebSocketClose: (event) => {
console.warn('WebSocket соединение закрыто:', event.code, event.reason);
}
});
WebSocket-ошибки не содержат бизнес-логики STOMP. Они не дают информации о подписках или очередях. Это исключительно транспортный уровень.
Закрытие соединения может происходить:
Для восстановления соединения используется:
const client = new Client({
brokerURL: 'ws://localhost:15674/ws',
reconnectDelay: 5000
});
reconnectDelay активирует автоматический реконнект после
разрыва.
STOMP-протокол предусматривает специальный frame ERROR,
который отправляется брокером при логических ошибках: неправильные
подписки, ошибки авторизации, отказ в доступе к destination.
В STOMP.js это обрабатывается через:
const client = new Client({
brokerURL: 'ws://localhost:15674/ws',
onStompError: (frame) => {
console.error('STOMP ошибка');
console.error('Заголовки:', frame.headers);
console.error('Сообщение:', frame.body);
}
});
Обычно содержит:
message — краткое описаниеcontent-typeПример:
message: "Unauthorized"
body: "User not allowed to access /queue/orders"
Подключение STOMP проходит несколько стадий: создание WebSocket, handshake, CONNECT frame, подтверждение CONNECTED.
Ошибки могут возникать на любом этапе.
const client = new Client({
brokerURL: 'ws://localhost:15674/ws',
onConnect: () => {
console.log('Подключение установлено');
},
onStompError: (frame) => {
console.error('Ошибка STOMP:', frame.body);
}
});
Подписка в STOMP.js не гарантирует успешную регистрацию на брокере. Ошибки могут проявляться как:
const subscription = client.subscribe('/queue/orders', (message) => {
console.log('Получено:', message.body);
});
STOMP не предоставляет callback “onSubscribeError” напрямую. Поэтому обработка строится косвенно:
STOMP поддерживает механизм receipt, который позволяет
отслеживать выполнение команд (SEND, SUBSCRIBE, UNSUBSCRIBE).
client.subscribe('/queue/orders', handler, {
receipt: 'sub-001'
});
Обработка подтверждения:
client.onRece ipt = (frame) => {
console.log('Receipt получен:', frame.headers['receipt-id']);
};
Если receipt не приходит, это индикатор:
Отправка сообщений может завершаться ошибкой не сразу, а на стороне брокера.
client.publish({
destination: '/queue/orders',
body: JSON.stringify({ id: 1 }),
headers: {
persistent: 'true'
}
});
Ошибки проявляются через:
Даже при успешной доставке сообщения ошибка может возникнуть на уровне обработки payload.
client.subscribe('/queue/orders', (message) => {
try {
const data = JSON.parse(message.body);
processOrder(data);
} catch (e) {
console.error('Ошибка обработки сообщения:', e);
}
});
Heartbeat используется для определения “живости” соединения.
const client = new Client({
brokerURL: 'ws://localhost:15674/ws',
heartbeatIncoming: 10000,
heartbeatOutgoing: 10000
});
Если heartbeat не приходит:
STOMP.js позволяет отслеживать низкоуровневые проблемы через debug:
const client = new Client({
debug: (str) => {
console.log('DEBUG:', str);
}
});
Это важно при:
Некоторые ошибки не попадают в стандартные callback-и:
Для контроля состояния используется комбинация:
let lastActivity = Date.now();
client.subscribe('/queue/orders', (msg) => {
lastActivity = Date.now();
});
setInterval(() => {
if (Date.now() - lastActivity > 30000) {
console.warn('Нет активности от брокера');
}
}, 5000);
Если брокер требует авторизацию, ошибки могут приходить на этапе CONNECT:
const client = new Client({
brokerURL: 'ws://localhost:15674/ws',
connectHeaders: {
login: 'user',
passcode: 'wrong-password'
},
onStompError: (frame) => {
console.error('Auth ошибка:', frame.body);
}
});
Ошибки в STOMP.js условно делятся на два класса:
Используется комбинация механизмов:
const client = new Client({
brokerURL: 'ws://localhost:15674/ws',
reconnectDelay: 5000,
heartbeatIncoming: 10000,
heartbeatOutgoing: 10000,
onStompError: (frame) => {
logError(frame.body);
},
onWebSocketClose: () => {
notify('connection lost');
}
});
При построении устойчивых систем STOMP.js обычно рассматривается не как транспорт “с гарантией доставки”, а как слой, требующий внешнего контроля состояния и повторных попыток на уровне приложения.