Long Polling vs WebSocket в JavaScript: эпическая битва за real-time
Когда-то давно, в эпоху, когда интернет был медленным, а браузеры — простодушными, единственным способом узнать, что на сервере появились новые данные, было нажать F5. Потом появился AJAX, и мы научились дёргать сервер вручную. Но что, если данные должны приходить сами, без нашего участия? Добро пожаловать в мир real-time коммуникаций.
В этой статье мы разберём два главных подхода, которые до сих пор делят сообщество разработчиков: старый добрый Long Polling и современный, дерзкий WebSocket. Мы напишем код на JavaScript, посмотрим на их внутренности и поймём, какой инструмент выбрать для вашего следующего проекта. Если вы хотите разобраться в long polling vs websocket раз и навсегда — вы по адресу.
Проблема: как заставить сервер говорить первым?
HTTP — протокол однонаправленный. Клиент (браузер) шлёт запрос, сервер отвечает — и всё, обед окончен. Но в реальном мире (чаты, биржевые котировки, уведомления) данные должны течь в обратную сторону. Долгое время разработчики изворачивались. И вот два основных способа решить эту проблему.
Long Polling: хитрый трюк со временем
Представьте, что вы звоните в службу поддержки и говорите: «Я подожду на линии, пока освободится оператор». Вы не кладёте трубку. Именно так работает Long Polling (он же «длинный опрос»).
Как это работает:
- Клиент отправляет обычный HTTP-запрос.
- Сервер не отвечает сразу, если данных нет. Он «висит» и ждёт.
- Как только появляются данные — сервер шлёт ответ.
- Клиент обрабатывает ответ и тут же открывает новое соединение.
Код на клиенте (JavaScript):
function longPoll() {
fetch('/updates')
.then(response => response.json())
.then(data => {
console.log('Новые данные:', data);
// Сразу начинаем новый опрос
longPoll();
})
.catch(error => {
console.error('Ошибка, переподключаемся через 2 сек:', error);
setTimeout(longPoll, 2000);
});
}
// Запускаем
longPoll();
Плюсы:
- Работает на любом сервере и любом браузере (даже на IE6).
- Не требует специальных протоколов — чистый HTTP.
- Проходит через любые корпоративные прокси и файрволы.
Минусы:
- Каждое сообщение — это новый HTTP-запрос (заголовки, куки, накладные расходы).
- Сервер держит много открытых соединений (проблема C10k — 10 тысяч клиентов).
- Задержка (latency) выше, чем у WebSocket.
WebSocket: постоянный канал связи
WebSocket — это как открытая линия между космическим кораблём и центром управления. Вы устанавливаете соединение один раз, и дальше обе стороны могут слать данные в любой момент, без лишних церемоний.
Как это работает:
- Клиент инициирует handshake (рукопожатие) через HTTP.
- Сервер переключает протокол на ws:// или wss://.
- Устанавливается постоянное двунаправленное соединение.
- Данные передаются фреймами — легковесно и быстро.
Код на клиенте (JavaScript):
const socket = new WebSocket('wss://example.com/chat');
// Когда соединение открыто
socket.onopen = function() {
console.log('Соединение установлено');
socket.send(JSON.stringify({ type: 'greeting', text: 'Привет, сервер!' }));
};
// Когда пришло сообщение
socket.onmessage = function(event) {
const data = JSON.parse(event.data);
console.log('Сообщение от сервера:', data);
};
// При ошибке
socket.onerror = function(error) {
console.error('Ошибка WebSocket:', error);
};
// При закрытии
socket.onclose = function(event) {
console.log('Соединение закрыто. Код:', event.code);
// Можно переподключиться
setTimeout(() => { /* reconnect logic */ }, 3000);
};
Плюсы:
- Минимальный overhead — нет заголовков HTTP в каждом сообщении.
- Настоящий real-time: данные приходят мгновенно.
- Одно соединение на сессию — меньше нагрузки на сервер.
Минусы:
- Сложнее с прокси и файрволами (некоторые корпоративные сети блокируют WebSocket).
- Требует серверной поддержки (Node.js, Python с asyncio, Java Netty и т.д.).
- Нужно управлять переподключением и heartbeat (пинг-понг).
Сравнительная таблица: Long Polling vs WebSocket
| Характеристика | Long Polling | WebSocket |
|---|---|---|
| Протокол | HTTP/1.1 | WebSocket (ws:// или wss://) |
| Тип соединения | Дискретные запросы | Постоянное соединение |
| Задержка (latency) | Средняя (зависит от RTT) | Низкая (почти мгновенно) |
| Количество соединений | Много (каждый запрос — новое) | Одно на клиента |
| Сложность реализации | Низкая | Средняя (нужен менеджер соединений) |
| Совместимость | Отличная (все браузеры) | Хорошая (IE10+, все современные) |
| Использование | Редко обновляемые данные | Частые обновления, игры, чаты |
Когда что выбирать? Практические сценарии
Давайте честно: вопрос «Long Polling или WebSocket» — это не битва добра со злом. Это вопрос уместности. Вот несколько сценариев, где каждый из них показывает себя лучше.
Когда использовать Long Polling
- Простое уведомление — например, «у вас новое письмо» раз в 5 минут. Не нужно держать постоянный канал.
- Корпоративные системы —