Реализация Background Sync для PWA

Наша компания занимается разработкой, поддержкой и обслуживанием сайтов любой сложности. От простых одностраничных сайтов до масштабных кластерных систем построенных на микро сервисах. Опыт разработчиков подтвержден сертификатами от вендоров.
Разработка и обслуживание любых видов сайтов:
Информационные сайты или веб-приложения
Сайты визитки, landing page, корпоративные сайты, онлайн каталоги, квиз, промо-сайты, блоги, новостные ресурсы, информационные порталы, форумы, агрегаторы
Сайты или веб-приложения электронной коммерции
Интернет-магазины, B2B-порталы, маркетплейсы, онлайн-обменники, кэшбэк-сайты, биржи, дропшиппинг-платформы, парсеры товаров
Веб-приложения для управления бизнес-процессами
CRM-системы, ERP-системы, корпоративные порталы, системы управления производством, парсеры информации
Сайты или веб-приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, конструкторы сайтов, порталы предоставления электронных услуг, видеохостинги, тематические порталы

Это лишь некоторые из технических типов сайтов, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента

Предлагаемые услуги
Показано 1 из 1 услугВсе 2065 услуг
Реализация Background Sync для PWA
Средняя
~2-3 рабочих дня
Часто задаваемые вопросы
Наши компетенции:
Этапы разработки
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1262
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1171
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    874
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1094
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    831
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Разработка веб-сайта для компании ФИКСПЕР
    851

Реализация Background Sync для PWA

Background Sync позволяет Service Worker выполнить отложенное действие (отправить форму, синхронизировать данные) при восстановлении соединения — даже если пользователь уже закрыл вкладку.

Как работает Background Sync

  1. Пользователь выполняет действие (кладёт товар в корзину) — нет интернета
  2. Приложение сохраняет задачу в IndexedDB и регистрирует sync-тег
  3. Браузер ждёт сетевого соединения
  4. Service Worker получает событие sync и выполняет отложенную задачу
  5. При неудаче — браузер повторит попытку с экспоненциальной задержкой

Регистрация sync из страницы

// background-sync.ts
type SyncAction = {
    type: 'cart' | 'wishlist' | 'form' | 'review';
    payload: Record<string, unknown>;
    createdAt: number;
};

async function queueAction(action: SyncAction): Promise<void> {
    // 1. Сохранить в IndexedDB
    const db = await openDatabase();
    await db.put('syncQueue', { ...action, id: Date.now() });

    // 2. Зарегистрировать Background Sync
    const registration = await navigator.serviceWorker.ready;

    if ('sync' in registration) {
        await (registration as any).sync.register(`sync-${action.type}`);
    } else {
        // Fallback для браузеров без Background Sync
        if (navigator.onLine) {
            await processAction(action);
        }
    }
}

// Открытие IndexedDB
async function openDatabase(): Promise<IDBDatabase> {
    return new Promise((resolve, reject) => {
        const request = indexedDB.open('PWASync', 1);
        request.onupgradeneeded = e => {
            (e.target as IDBOpenDBRequest).result
                .createObjectStore('syncQueue', { keyPath: 'id' });
        };
        request.onsuccess = e => resolve((e.target as IDBOpenDBRequest).result);
        request.onerror = reject;
    });
}

Service Worker: обработка sync-событий

// sw.js
self.addEventListener('sync', event => {
    console.log('Background sync triggered:', event.tag);

    switch (event.tag) {
        case 'sync-cart':
            event.waitUntil(syncCart());
            break;
        case 'sync-wishlist':
            event.waitUntil(syncWishlist());
            break;
        case 'sync-form':
            event.waitUntil(syncPendingForms());
            break;
        case 'sync-review':
            event.waitUntil(syncPendingReviews());
            break;
    }
});

async function syncCart() {
    const db = await openIDB('PWASync', 1);
    const tx = db.transaction('syncQueue', 'readwrite');
    const store = tx.objectStore('syncQueue');

    const actions = await getAllFromStore(store, 'cart');

    for (const action of actions) {
        const response = await fetch('/api/cart/items', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'X-Sync': 'background',
            },
            body: JSON.stringify(action.payload),
        });

        if (response.ok) {
            await store.delete(action.id);
            // Уведомить открытые вкладки о синхронизации
            const clients = await self.clients.matchAll();
            clients.forEach(client => {
                client.postMessage({ type: 'CART_SYNCED', payload: action.payload });
            });
        } else if (response.status >= 400 && response.status < 500) {
            // Клиентская ошибка — удалить, не повторять
            await store.delete(action.id);
        }
        // 5xx — оставить для повтора (браузер повторит sync автоматически)
    }
}

Periodic Background Sync (Chrome)

Позволяет выполнять задачи по расписанию — обновлять курс валют, новости, прогноз погоды:

// Регистрация
async function registerPeriodicSync() {
    const registration = await navigator.serviceWorker.ready;

    if ('periodicSync' in registration) {
        const status = await navigator.permissions.query({ name: 'periodic-background-sync' as any });

        if (status.state === 'granted') {
            await (registration as any).periodicSync.register('update-prices', {
                minInterval: 60 * 60 * 1000, // не чаще раза в час
            });
        }
    }
}
// sw.js: periodic sync
self.addEventListener('periodicsync', event => {
    if (event.tag === 'update-prices') {
        event.waitUntil(updateCachedPrices());
    }
});

async function updateCachedPrices() {
    const response = await fetch('/api/prices/current');
    const prices = await response.json();

    const cache = await caches.open('dynamic-v1');
    // Обновить закешированные данные
    await cache.put('/api/prices/current', new Response(JSON.stringify(prices), {
        headers: { 'Content-Type': 'application/json' }
    }));

    // Уведомить пользователя если цена на избранный товар изменилась
    await checkWishlistPriceChanges(prices);
}

Отображение статуса синхронизации

// useSyncStatus.ts
export function useSyncStatus() {
    const [pendingCount, setPendingCount] = useState(0);
    const [isSyncing, setIsSyncing] = useState(false);

    useEffect(() => {
        // Слушать сообщения от Service Worker
        const handler = (event: MessageEvent) => {
            if (event.data.type === 'CART_SYNCED') {
                setPendingCount(c => Math.max(0, c - 1));
                setIsSyncing(false);
            }
            if (event.data.type === 'SYNC_STARTED') {
                setIsSyncing(true);
            }
        };

        navigator.serviceWorker.addEventListener('message', handler);
        return () => navigator.serviceWorker.removeEventListener('message', handler);
    }, []);

    return { pendingCount, isSyncing };
}

// В компоненте хедера
function SyncIndicator() {
    const { pendingCount, isSyncing } = useSyncStatus();

    if (pendingCount === 0) return null;

    return (
        <div className="sync-indicator">
            {isSyncing ? 'Синхронизация...' : `${pendingCount} действий ожидают синхронизации`}
        </div>
    );
}

Срок реализации: 1–2 дня для базового Background Sync с корзиной и формами.