نحوه همگام سازی دوره ای داده ها در پس زمینه

سیسیلیا کانگ
Cecilia Cong

روش مدرن

همگام‌سازی دوره‌ای پس‌زمینه به شما امکان می‌دهد هنگام راه‌اندازی یک برنامه وب پیش‌رونده یا صفحه‌ای تحت حمایت کارگران خدمات، محتوای تازه را نشان دهید. وقتی از برنامه یا صفحه استفاده نمی شود، این کار را با بارگیری داده ها در پس زمینه انجام می دهد.

با استفاده از Periodic Background Sync API

پس از نصب سرویس‌کار، از Permissions API برای جستجوی periodic-background-sync استفاده کنید. شما می توانید این کار را از یک پنجره یا یک زمینه سرویس کار انجام دهید.

const status = await navigator.permissions.query({
  name: 'periodic-background-sync',
});
if (status.state === 'granted') {
  // Periodic background sync can be used.
} else {
  // Periodic background sync cannot be used.
}

ثبت یک همگام سازی دوره ای به هر دو برچسب و حداقل فاصله همگام سازی ( minInterval ) نیاز دارد. تگ همگام سازی ثبت شده را مشخص می کند تا بتوان همگام سازی های متعدد را ثبت کرد. در مثال زیر، نام تگ 'content-sync' و minInterval یک روز است.

navigator.serviceWorker.ready.then(async registration => {
  try {
    await registration.periodicSync.register('get-cats', { minInterval: 24 * 60 * 60 * 1000 });
    console.log(Periodic background sync registered.');
  } catch (err) {
    console.error(err.name, err.message);
  }
});

برای بازیابی آرایه ای از تگ های ثبت نام periodicSync.getTags() فراخوانی کنید. مثال زیر از نام‌های برچسب برای تأیید فعال بودن به‌روزرسانی حافظه پنهان استفاده می‌کند تا از به‌روزرسانی مجدد جلوگیری شود.

const registration = await navigator.serviceWorker.ready;
if ('periodicSync' in registration) {
  const tags = await registration.periodicSync.getTags();
  // Only update content if sync isn't set up.
  if (!tags.includes('content-sync')) {
    updateContentOnPageLoad();
  }
} else {
  // If periodic background sync isn't supported, always update.
  updateContentOnPageLoad();
}

برای پاسخ به یک رویداد همگام‌سازی پس‌زمینه دوره‌ای، یک کنترل‌کننده رویداد periodicsync را به سرویس‌کار خود اضافه کنید. شئ رویدادی که به آن ارسال می‌شود دارای یک پارامتر برچسب منطبق با مقدار مورد استفاده در هنگام ثبت است. برای مثال، اگر یک همگام‌سازی دوره‌ای پس‌زمینه با نام 'content-sync' ثبت شده باشد، آنگاه event.tag 'content-sync' خواهد بود.

self.addEventListener('periodicsync', (event) => {
  if (event.tag === 'content-sync') {
    event.waitUntil(syncContent());
  }
});

سازگاری با مرورگر

پشتیبانی مرورگر

  • 80
  • 80
  • ایکس
  • ایکس

منبع

روش کلاسیک

به‌جای به‌روزرسانی داده‌ها در پس‌زمینه تا زمانی که کاربر برنامه را بارگیری می‌کند آماده باشد، روش کلاسیک به سادگی شامل به‌روزرسانی داده‌ها در زمان بارگذاری است.

بیشتر خواندن

نسخه ی نمایشی

HTML

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <link
      rel="icon"
      href=""
    />
    <link rel="manifest" href="./manifest.json" />
    <title>How to periodically synchronize data in the background</title>
    <link rel="stylesheet" href="/style.css" />
    <!-- TODO: Devsite - Removed inline handlers -->
    <!-- <script src="/script.js" defer></script> -->
  </head>
  <body>
    <h1>How to periodically synchronize data in the background</h1>
    <p class="available">Periodic background sync can be used. Install the app first.</p>
    <p class="not-available">Periodic background sync cannot be used.</p>
    <h2>Last updated</h2>
    <p class="last-updated">Never</p>
    <h2>Registered tags</h2>
    <ul>
      <li>None yet.</li>
    </ul>
  </body>
</html>

CSS


        html {
  box-sizing: border-box;
  font-family: system-ui, sans-serif;
  color-scheme: dark light;
}

*,
*:before,
*:after {
  box-sizing: inherit;
}

body {
  margin: 1rem;
}
        

JS


        const available = document.querySelector('.available');
const notAvailable = document.querySelector('.not-available');
const ul = document.querySelector('ul');
const lastUpdated = document.querySelector('.last-updated');

const updateContent = async () => {
  const data = await fetch(
    'https://worldtimeapi.org/api/timezone/Europe/London.json'
  ).then((response) => response.json());
  return new Date(data.unixtime * 1000);
};

const registerPeriodicBackgroundSync = async (registration) => {
  const status = await navigator.permissions.query({
    name: 'periodic-background-sync',
  });
  if (status.state === 'granted' && 'periodicSync' in registration) {
    try {
      // Register the periodic background sync.
      await registration.periodicSync.register('content-sync', {
        // An interval of one day.
        minInterval: 24 * 60 * 60 * 1000,
      });
      available.hidden = false;
      notAvailable.hidden = true;

      // List registered periodic background sync tags.
      const tags = await registration.periodicSync.getTags();
      if (tags.length) {
        ul.innerHTML = '';
      }
      tags.forEach((tag) => {
        const li = document.createElement('li');
        li.textContent = tag;
        ul.append(li);
      });

      // Update the user interface with the last periodic background sync data.
      const backgroundSyncCache = await caches.open('periodic-background-sync');
      if (backgroundSyncCache) {
        const backgroundSyncResponse =
          backgroundSyncCache.match('/last-updated');
        if (backgroundSyncResponse) {
          lastUpdated.textContent = `${await fetch('/last-updated').then(
            (response) => response.text()
          )} (periodic background-sync)`;
        }
      }

      // Listen for incoming periodic background sync messages.
      navigator.serviceWorker.addEventListener('message', async (event) => {
        if (event.data.tag === 'content-sync') {
          lastUpdated.textContent = `${await updateContent()} (periodic background sync)`;
        }
      });
    } catch (err) {
      console.error(err.name, err.message);
      available.hidden = true;
      notAvailable.hidden = false;
      lastUpdated.textContent = 'Never';
    }
  } else {
    available.hidden = true;
    notAvailable.hidden = false;
    lastUpdated.textContent = `${await updateContent()} (manual)`;
  }
};

if ('serviceWorker' in navigator) {
  window.addEventListener('load', async () => {
    const registration = await navigator.serviceWorker.register('./sw.js');
    console.log('Service worker registered for scope', registration.scope);

    await registerPeriodicBackgroundSync(registration);
  });
}