Pollyx

v1.0.4 React / Vue 3 20.2 kB gzip
Pollyx — это легковесная JavaScript-библиотека для организации поллинга с поддержкой WebSocket и интеллектуальными diff-обновлениями. В отличие от классического подхода, где каждый запрос перезагружает весь блок данных, Pollyx анализирует изменения и применяет только их — это экономит трафик, сохраняет фокус ввода и обеспечивает плавность интерфейса. Библиотека идеально подходит для финансовых дашбордов, интернет-магазинов и любых проектов, где важна актуальность данных без потери производительности. С готовыми адаптерами для React и Vue 3 вы можете внедрить умный поллинг в существующий проект за минуты.
https://github.com/kartovitskii/pollyx
Конструктор Методы экземпляра Статические методы RetryStrategy События Глобальные обработчики Адаптеры CDN подключение

🔧 Конструктор

new Pollyx(element: HTMLElement | string, options: PollyxOptions): PollyxInstance

Параметры конструктора

Параметр Тип Обязательный Описание
element HTMLElement | string да DOM-элемент или CSS-селектор, содержимое которого будет обновляться
options PollyxOptions да Объект конфигурации (см. таблицу ниже)

Интерфейс PollyxOptions

Поле Тип По умолчанию Описание
interval number 60000 Интервал опроса в миллисекундах
url string URL для запросов (обязательное поле)
method 'GET' | 'POST' | 'PUT' | 'PATCH' 'GET' HTTP метод
headers Record<string, string> { 'X-Requested-With': 'XMLHttpRequest', 'Accept': 'text/html' } Заголовки запроса
body Document | XMLHttpRequestBodyInit | null null Тело запроса (для POST/PUT)
retry RetryOptions { maxAttempts: 3, baseDelay: 1000, maxDelay: 30000, factor: 2, jitter: true } Настройки повторных попыток
websocket WebSocketOptions { enabled: false, url: '', fallbackAfter: 3, reconnectInterval: 5000 } Настройки WebSocket
deduplicate boolean true Дедупликация одновременных запросов
diffUpdates boolean true Использовать diff-match-patch для обновлений
preserveFocus boolean true Сохранять фокус и выделение при обновлениях
autoStart boolean true Автоматический запуск после создания
debug boolean false Режим отладки (логи в консоль)
onUpdate (html: string, instance: PollyxInstance) => void undefined Колбэк после успешного обновления
onError (error: Error, instance: PollyxInstance) => void undefined Колбэк при ошибке
onStatusChange (status: StatusType, data: any, instance: PollyxInstance) => void undefined Колбэк при смене статуса

Интерфейс RetryOptions

maxAttempts number 3 Максимальное количество попыток
baseDelay number 1000 Базовая задержка (мс)
maxDelay number 30000 Максимальная задержка (мс)
factor number 2 Множитель задержки (exponential backoff)
jitter boolean true Случайная вариация задержки

Интерфейс WebSocketOptions

enabled boolean false Включить WebSocket
url string '' WebSocket URL (wss:// или ws://)
fallbackAfter number 3 Количество ошибок WS до переключения на polling
reconnectInterval number 5000 Интервал переподключения (мс)

📌 Методы экземпляра

Управление жизненным циклом

start(): void

Запускает поллинг. Если уже запущен — ничего не делает. Генерирует событие started.

stop(): void

Останавливает поллинг. Генерирует событие stopped.

destroy(): void

Полностью уничтожает инстанс: останавливает все таймеры, закрывает WebSocket, удаляет обработчики событий. Инстанс удаляется из глобального реестра.

refetch(): Promise<string>

Принудительно выполняет запрос немедленно, игнорируя текущий интервал. Возвращает Promise с полученным HTML.

Настройка и состояние

updateOptions(newOptions: Partial<PollyxOptions>): void

Обновляет опции инстанса. Может быть вызван в любой момент. Особенности:

getState(): PollyxState

Возвращает текущее состояние инстанса:

interface PollyxState {
    status: 'idle' | 'fetching' | 'success' | 'error' | 'stopped' | 'ws_connected' | 'ws_fallback';
    lastHtml: string | null;           // последний полученный HTML
    lastFetchTime: number | null;      // timestamp последнего запроса
    errorCount: number;                // счётчик ошибок подряд
    retryState: RetryState;            // состояние RetryStrategy
    wsConnected: boolean;              // флаг подключения WebSocket
}
isActive(): boolean

Возвращает true, если инстанс запущен и не уничтожен.

Глобальные обработчики

registerHandler(name: string, handler: GlobalHandler): void

Регистрирует обработчик для элементов с атрибутом data-pollyx-handler="{name}" внутри текущего элемента.

type GlobalHandler = (
    newHtml: string,
    oldHtml: string,
    instance: PollyxInstance,
    diff?: PatchObject[]  // только если diffUpdates: true
) => void;
unregisterHandler(name: string): boolean

Удаляет зарегистрированный обработчик. Возвращает true, если обработчик существовал.

Управление WebSocket

connectWebSocket(): void

Принудительно инициирует подключение WebSocket (если websocket.enabled === true).

disconnectWebSocket(): void

Закрывает WebSocket-соединение.

fallbackToPolling(reason?: string): void

Принудительно переключает инстанс в режим polling (отключает WebSocket). Генерирует событие ws_fallback.

🌐 Статические методы класса Pollyx

Pollyx.registerHandler(name: string, handler: GlobalHandler): void

Регистрирует глобальный обработчик для всех инстансов. Будет вызван для любого элемента с data-pollyx-handler="{name}" в любом инстансе.

Pollyx.unregisterHandler(name: string): boolean

Удаляет глобальный обработчик.

Pollyx.getAllInstances(): PollyxInstance[]

Возвращает массив всех созданных инстансов.

Pollyx.startAll(): void

Запускает все остановленные инстансы.

Pollyx.stopAll(): void

Останавливает все активные инстансы.

Pollyx.destroyAll(): void

Уничтожает все инстансы и очищает реестр.

Pollyx.setDefaultOptions(options: Partial<PollyxOptions>): void

Устанавливает опции по умолчанию для всех новых инстансов.

🔄 Класс RetryStrategy

Используется внутренне, но также доступен для прямого использования.

new RetryStrategy(options: RetryOptions)

Методы RetryStrategy

Метод Возвращает Описание
shouldRetry(attempt: number, error?: Error) boolean Проверяет, нужно ли повторить попытку
getDelayForAttempt(attempt: number) number Возвращает задержку (мс) для указанной попытки
getState() RetryState Возвращает текущее состояние
reset() void Полный сброс (attempt = 0, lastError = null)
resetAttempts() void Сброс счётчика попыток, но сохранение startTime
isReset() boolean Проверяет, был ли сброс после последней ошибки
interface RetryState {
    attempt: number;              // текущая попытка (0 - первая)
    lastAttempt: number | null;   // timestamp последней попытки
    lastError: Error | null;      // последняя ошибка
    lastDelay: number | null;     // последняя использованная задержка
    exceededMaxAttempts: boolean; // превышен лимит попыток
    aborted: boolean;             // была ли принудительная остановка
    startTime: number;            // время создания стратегии
}

📡 Система событий

Каждый инстанс генерирует события на своём DOM-элементе. Слушать можно через addEventListener.

element.addEventListener('pollyx:status', handler)

Объект события

interface PollyxStatusEvent extends CustomEvent {
    detail: {
        status: StatusType;
        instance: PollyxInstance;
        timestamp: number;
        data?: any;
    }
}

Типы статусов и их data

Статус Структура data Описание
'started' undefined Поллинг запущен
'stopped' undefined Поллинг остановлен
'fetching' { fetchId: string } Начат запрос
'success' { response: string, fetchId: string } Запрос успешен
'error' { error: Error, fetchId?: string } Ошибка запроса
'retrying' { attempt: number, delay: number, error: Error } Повторная попытка
'diff_applied' { patchesCount: number, failedPatches: number, time: number } Применён diff
'handler_registered' { name: string } Зарегистрирован глобальный обработчик
'ws_connected' undefined WebSocket подключён
'ws_disconnected' { code?: number, reason?: string } WebSocket отключён
'ws_error' { error: Event } Ошибка WebSocket
'ws_fallback' { reason?: string } Переключение на polling

🎯 Глобальные обработчики (data-pollyx)

Позволяют выполнять произвольный код при обновлении конкретных элементов внутри контейнера.

HTML-разметка

<div data-pollyx>
    <!-- Обычное содержимое -->
    <div data-pollyx-handler="highlight">
        Этот элемент будет обработан специальным обработчиком
    </div>

    <div data-pollyx-handler="logger" data-pollyx-param="user-123">
        Можно добавлять любые data-атрибуты
    </div>
</div>

Регистрация обработчика

// Глобальный (для всех инстансов)
Pollyx.registerHandler('highlight', (newHtml, oldHtml, instance, diff) => {
    console.log('Изменения для элемента:', instance.element);
    // diff доступен только если options.diffUpdates = true
});

// Локальный (только для конкретного инстанса)
polling.registerHandler('logger', (newHtml, oldHtml, instance) => {
    console.log('Получен новый HTML для логгера');
});
Важно: Обработчики вызываются после обновления DOM. Если вам нужно выполнить код до обновления, используйте событие fetching.

⚛️ Адаптеры для фреймворков

React (usePolling)

usePolling(options: UsePollingOptions): UsePollingResult

Параметры usePolling

Поле Тип Описание
url string URL для запросов
interval number Интервал (мс)
method? string HTTP метод
headers? Record<string, string> Заголовки
body? any Тело запроса
retry? RetryOptions Настройки повторов
websocket? WebSocketOptions Настройки WebSocket
diffUpdates? boolean Использовать diff
autoStart? boolean Автостарт
onUpdate? (html: string) => void Колбэк обновления
onError? (error: Error) => void Колбэк ошибки

Возвращаемое значение

interface UsePollingResult {
    data: string | null;           // последние полученные данные
    isFetching: boolean;            // выполняется ли запрос
    error: Error | null;            // ошибка (если есть)
    refetch: () => Promise<string>; // принудительный запрос
    status: StatusType;             // текущий статус
    start: () => void;              // запустить поллинг
    stop: () => void;               // остановить
}

Vue 3 (usePollingVue)

usePollingVue(options: UsePollingOptions): UsePollingVueResult

Возвращает те же поля, что и React-версия, но в виде ref-объектов (для реактивности Vue).

🌐 Подключение через CDN

Важно! Для работы diff-обновлений необходимо подключать diff_match_patch до библиотеки Pollyx.

<!DOCTYPE html>
<html>
<head>
    <!-- Сначала подключаем diff-match-patch (обязательно для diffUpdates) -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/diff_match_patch/20121119/diff_match_patch.js"></script>

    <!-- Затем подключаем саму библиотеку Pollyx -->
    <script src="https://unpkg.com/pollyx@1.0.4/dist/pollyx.umd.js"></script>
</head>
<body>
    <div id="app">
        <div id="content">Загрузка...</div>
    </div>

    <script>
        // Pollyx доступен глобально как window.Pollyx
        const { Pollyx } = window.Pollyx;

        const container = document.getElementById('app');
        const polling = new Pollyx(container, {
            url: '/api/updates',
            interval: 5000,
            diffUpdates: true,      // будет работать благодаря diff_match_patch
            onUpdate: (html) => {
                console.log('Обновлено!', html);
            }
        });

        // polling.start() вызывается автоматически (autoStart: true)
    </script>
</body>
</html>