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

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

روش مدرن

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

استفاده از API همگام‌سازی دوره‌ای پس‌زمینه

پس از نصب سرویس ورکر، از 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() را فراخوانی کنید. مثال زیر از نام تگ‌ها برای تأیید فعال بودن به‌روزرسانی حافظه پنهان (cache) و جلوگیری از به‌روزرسانی مجدد استفاده می‌کند.

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 به سرویس ورکر خود اضافه کنید. شیء رویداد ارسالی به آن شامل یک پارامتر tag خواهد بود که با مقداری که هنگام ثبت استفاده شده است، مطابقت دارد. برای مثال، اگر یک همگام‌سازی پس‌زمینه دوره‌ای با نام 'content-sync' ثبت شده باشد، event.tag برابر با 'content-sync' خواهد بود.

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

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

Browser Support

  • کروم: ۸۰.
  • لبه: ۸۰.
  • فایرفاکس: پشتیبانی نمی‌شود.
  • سافاری: پشتیبانی نمی‌شود.

Source

روش کلاسیک

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

مطالعه بیشتر

نسخه آزمایشی

اچ‌تی‌ام‌ال

<!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>

سی‌اس‌اس


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

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

body {
  margin: 1rem;
}
        

جی‌اس


        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);
  });
}