Пейджер

🌍 Привет мир! 👋🏻

🌍 Привет мир! 👋🏻

Часто требуется передавать обновления клиентам мгновенно, как только они появляются. Обычно для этого используют подходы вроде Polling или WebSockets, но не все знают о простом и эффективном решении — Server-Sent Events (SSE).

Что такое SSE

Это подход при котором происходит однонаправленная передача данных от сервера к клиенту, через HTTP-соединение.

👍🏻 Преимущества SSE

Автоматическое переподключение: Браузер автоматически восстанавливает соединение с сервером в случае его разрыва, что делает приложение устойчивым и лёгким в поддержке.
Небольшие затраты ресурсов: SSE потребляет меньше ресурсов по сравнению с WebSockets, так как это простой, односторонний протокол.
Кросс-браузерность: Современные браузеры, такие как Chrome, Firefox и Safari, имеют встроенную поддержку SSE.

⚙️ Как работает SSE?

➖ Клиент делает обычный HTTP-запрос к серверу.
➖ Сервер поддерживает это соединение открытым и отправляет данные в формате text/event-stream.
➖ Клиент слушает сервер и обрабатывает поступающие данные.

🛠 Технические детали имплементации

Сервер отвечает с типом контента text/event-stream, а сами данные отправляются в следующем формате:

📌 data: Может содержать несколько строк, каждая заканчивается переводом строки (\n). Каждое сообщение, отправленное с сервера, должно начинаться с data:, за которым следует контент, и заканчиваться двумя переводами строк (\n\n). Это не просто какое-то соглашение — это требование протокола SSE.
📌 event (опционально): тип события.
📌 id (опционально): уникальный идентификатор, используется для того чтобы клиент мог отслеживать и восстанавливать соединения.

✏️ Небольшой пример (Back-end side) (кстати полную версию рабочего приложения можно посмотреть здесь)

app.get('/events', (req, res) => {
    res.setHeader('Content-Type', 'text/event-stream');
    res.setHeader('Cache-Control', 'no-cache');
    res.setHeader('Connection', 'keep-alive');

    res.write(`data: Connected to server\n\n`);

    let messageId = 0;

    const intervalId = setInterval(() => {
        messageId += 1;
        res.write(`id: ${messageId}\n`);
        res.write(`event: time-update\n`);
        res.write(`data: ${new Date().toLocaleTimeString()}\n\n`);
    }, 1000);

    req.on('close', () => {
        console.log('Client disconnected');
        clearInterval(intervalId);
        res.end();
    });
});


1️⃣ Открывается SSE endpoint (/events): Сервер устанавливает заголовки для SSE-соединения:
Content-Type: text/event-stream — определяет тип контента.
Cache-Control: no-cache — отключается кеширование.
Connection: keep-alive — указывается, что соединение нужно оставить открытым.

2️⃣ Первоначальное сообщение: Сервер сразу отправляет клиенту простое сообщение о подключении:

    Connected to server


3️⃣ Регулярная отправка сообщений: Каждую секунду отправляется новое событие:
➖ Уникальный идентификатор (id) для каждого события.
➖ Тип события — event: time-update.
➖ Данные (data) — текущее серверное время.

4️⃣ Закрытие соединения: Если клиент отключается (req.on('close')), сервер останавливает отправку сообщений, очищая таймер.

В результате: клиент получает регулярные обновления времени без необходимости самостоятельно отправлять запросы серверу.

Вся часть клиента (Front-end side) крутится вокруг EventSource, пример реализации.

‼️ Особенности:

👉🏻 Сервер может предоставлять любое количество SSE-каналов на разных URL-адресах.
👉🏻 Один поток SSE может передавать разные типы событий (уведомления, сообщения, обновления данных и тд.).
👉🏻 Если соединение ⛓️‍💥 обрывается, браузер автоматически отправляет серверу последний полученный идентификатор события (Last-Event-ID). Это позволяет серверу отправить клиенту пропущенные события после переподключения.
👉🏻 Сервер может завершить соединение: вызвав res.end()
👉🏻 Только браузер может восстановить соединение, создав новый объект EventSource.

💬 Делитесь своим мнением в комментариях👇! Если вам понравилась статья, не забудьте поставить лайк! 👍

#ARCHITECTURE
Медиа 1
Хотите больше таких постов?
Подпишитесь на канал и читайте продолжение в Telegram.
Подписаться на @ivanchikovitclub Открыть пост в Telegram