Background Sync — это механизм, позволяющий веб-приложениям синхронизировать данные с сервером в фоне, даже когда пользователь находится офлайн или сеть нестабильна. В сочетании с компонентной архитектурой Polymer этот подход обеспечивает надежное обновление состояния приложения и улучшает пользовательский опыт.
Background Sync реализуется через Service Workers и SyncManager. Service Worker перехватывает сетевые запросы, кеширует их при отсутствии соединения и инициирует повторную отправку, когда соединение восстанавливается. Polymer, будучи фреймворком для создания веб-компонентов, интегрируется с этим механизмом через кастомные элементы и реактивные свойства.
Основные шаги работы Background Sync:
Регистрация Service Worker
if ('serviceWorker' in navigator && 'SyncManager' in window) {
navigator.serviceWorker.register('/sw.js').then(reg => {
console.log('Service Worker зарегистрирован', reg);
});
}Регистрация синхронизации После попытки отправки данных при отсутствии сети необходимо зарегистрировать синхронизацию:
navigator.serviceWorker.ready.then(swRegistration => {
return swRegistration.sync.register('sync-data');
});Обработка события sync в Service Worker Service
Worker слушает событие sync и выполняет повторную отправку
данных:
self.addEventListener('sync', event => {
if (event.tag === 'sync-data') {
event.waitUntil(syncDataToServer());
}
});
async function syncDataToServer() {
const db = await openDatabase();
const unsyncedItems = await db.getAll('unsynced');
for (const item of unsyncedItems) {
await fetch('/api/data', {
method: 'POST',
body: JSON.stringify(item),
headers: { 'Content-Type': 'application/json' }
});
await db.delete('unsynced', item.id);
}
}В Polymer данные обычно хранятся в реактивных свойствах элементов. Для поддержки Background Sync целесообразно использовать локальное хранилище (IndexedDB) и синхронизировать его с сервером через Service Worker.
Пример создания компонента с офлайн-поддержкой:
import { PolymerElement, html } from '@polymer/polymer/polymer-element.js';
class OfflineForm extends PolymerElement {
static get properties() {
return {
formData: {
type: Object,
value: () => ({ name: '', email: '' })
}
};
}
static get template() {
return html`
<form on-submit="handleSubmit">
<input type="text" value="{{formData.name::input}}" placeholder="Имя">
<input type="email" value="{{formData.email::input}}" placeholder="Email">
<button type="submit">Отправить</button>
</form>
`;
}
async handleSubmit(e) {
e.preventDefault();
try {
await fetch('/api/data', {
method: 'POST',
body: JSON.stringify(this.formData),
headers: { 'Content-Type': 'application/json' }
});
} catch (err) {
await this.saveOffline(this.formData);
navigator.serviceWorker.ready.then(swReg => swReg.sync.register('sync-data'));
}
}
async saveOffline(data) {
const db = await openDatabase();
await db.put('unsynced', data);
}
}
customElements.define('offline-form', OfflineForm);
Для Background Sync важно организовать надежное хранение данных. Использование IndexedDB позволяет сохранять любые объекты и управлять синхронизацией:
function openDatabase() {
return new Promise((resolve, reject) => {
const request = indexedDB.open('app-db', 1);
request.onupgradenee ded = event => {
const db = event.target.result;
if (!db.objectStoreNames.contains('unsynced')) {
db.createObjectStore('unsynced', { keyPath: 'id', autoIncrement: true });
}
};
request.onsucc ess = event => resolve(event.target.result);
request.oner ror = event => reject(event.target.error);
});
}
Background Sync в сочетании с Polymer позволяет строить надежные офлайн-приложения, минимизируя потерю данных и обеспечивая плавное взаимодействие пользователя с интерфейсом даже при нестабильной сети.