معرفی Background Fetch

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

این یک ویژگی مفید است، اما مستلزم آن است که کارگر خدمات در طول مدت واکشی زنده باشد. این مشکلی برای کارهای کوتاه مانند ارسال پیام نیست، اما اگر این کار بیش از حد طول بکشد، مرورگر کارمند سرویس را می کشد، در غیر این صورت خطری برای حریم خصوصی و باتری کاربر است.

بنابراین، اگر نیاز به دانلود چیزی داشته باشید که ممکن است زمان زیادی طول بکشد، مانند یک فیلم، پادکست یا سطوح یک بازی، چه می‌کنید. Background Fetch برای همین است.

واکشی پس‌زمینه به‌طور پیش‌فرض از Chrome 74 در دسترس است.

در اینجا یک نسخه ی نمایشی سریع دو دقیقه ای وجود دارد که وضعیت سنتی چیزها را در مقایسه با استفاده از Background Fetch نشان می دهد:

خودتان نسخه ی نمایشی را امتحان کنید و کد را مرور کنید .

چگونه کار می کند

واکشی پس‌زمینه به این صورت عمل می‌کند:

  1. شما به مرورگر می‌گویید که گروهی از واکشی‌ها را در پس‌زمینه انجام دهد.
  2. مرورگر آن چیزها را واکشی می کند و پیشرفت را به کاربر نشان می دهد.
  3. هنگامی که واکشی کامل شد یا ناموفق بود، مرورگر سرویس‌کار شما را باز می‌کند و رویدادی را فعال می‌کند تا به شما بگوید چه اتفاقی افتاده است. این جایی است که شما تصمیم می گیرید که در صورت وجود پاسخ ها چه کاری انجام دهید.

اگر کاربر پس از مرحله 1 صفحات سایت شما را ببندد، اشکالی ندارد، دانلود ادامه خواهد یافت. از آنجایی که واکشی بسیار قابل مشاهده است و به راحتی قابل سقط است، نگرانی حفظ حریم خصوصی از یک کار همگام سازی پس زمینه بسیار طولانی وجود ندارد. از آنجایی که سرویس‌کار دائماً در حال اجرا نیست، این نگرانی وجود ندارد که بتواند از سیستم سوء استفاده کند، مانند استخراج بیت‌کوین در پس‌زمینه.

در برخی از پلتفرم‌ها (مانند Android) این امکان وجود دارد که مرورگر پس از مرحله 1 بسته شود، زیرا مرورگر می‌تواند واکشی را به سیستم عامل بسپارد.

اگر کاربر دانلود را در حالت آفلاین شروع کند، یا در حین دانلود آفلاین شود، واکشی پس‌زمینه متوقف می‌شود و بعداً از سر گرفته می‌شود.

API

تشخیص ویژگی

مانند هر ویژگی جدید، می‌خواهید تشخیص دهید که آیا مرورگر از آن پشتیبانی می‌کند یا خیر. برای Background Fetch، به همین سادگی است:

if ('BackgroundFetchManager' in self) {
  // This browser supports Background Fetch!
}

شروع واکشی پس‌زمینه

API اصلی یک سرویس‌کار ثبت نام را متوقف می‌کند، بنابراین مطمئن شوید که ابتدا یک سرویس‌کار را ثبت کرده‌اید. سپس:

navigator.serviceWorker.ready.then(async (swReg) => {
  const bgFetch = await swReg.backgroundFetch.fetch('my-fetch', ['/ep-5.mp3', 'ep-5-artwork.jpg'], {
    title: 'Episode 5: Interesting things.',
    icons: [{
      sizes: '300x300',
      src: '/ep-5-icon.png',
      type: 'image/png',
    }],
    downloadTotal: 60 * 1024 * 1024,
  });
});

backgroundFetch.fetch سه آرگومان می گیرد:

پارامترها
id string
این واکشی پس‌زمینه را به‌طور منحصربه‌فرد شناسایی می‌کند.

backgroundFetch.fetch اگر شناسه با واکشی پس‌زمینه موجود مطابقت داشته باشد رد می‌کند.

requests Array< Request |string>
چیزهایی که باید بیاورند رشته ها به عنوان URL در نظر گرفته می شوند و از طریق new Request(theString) به Request تبدیل می شوند.

تا زمانی که منابع اجازه دهند از طریق CORS می توانید چیزها را از مبداهای دیگر واکشی کنید.

توجه: Chrome در حال حاضر از درخواست‌هایی که نیاز به پیش‌بازی CORS دارند، پشتیبانی نمی‌کند.

options یک شی که ممکن است شامل موارد زیر باشد:
options.title string
عنوانی برای نمایش مرورگر همراه با پیشرفت.
options.icons Array< IconDefinition >
آرایه ای از اشیا با «src»، «size» و «type».
options.downloadTotal number
اندازه کل بدنه های پاسخ (پس از زیپ کردن).

اگرچه این اختیاری است، اما اکیداً توصیه می شود آن را ارائه دهید. از آن برای گفتن حجم دانلود به کاربر و ارائه اطلاعات پیشرفت استفاده می شود. اگر این را ارائه ندهید، مرورگر به کاربر می‌گوید اندازه آن ناشناخته است و در نتیجه احتمال لغو دانلود توسط کاربر بیشتر است.

اگر تعداد دانلودهای واکشی پس‌زمینه بیشتر از تعداد داده‌شده در اینجا باشد، لغو می‌شود. اگر دانلود کوچکتر از downloadTotal باشد، بسیار خوب است، بنابراین اگر مطمئن نیستید که مجموع دانلود چقدر خواهد بود، بهتر است احتیاط کنید.

backgroundFetch.fetch وعده ای را برمی گرداند که با BackgroundFetchRegistration حل می شود. من جزئیات آن را بعداً پوشش خواهم داد. اگر کاربر از دانلود انصراف داده باشد، یا یکی از پارامترهای ارائه شده نامعتبر باشد، قول رد می شود.

ارائه بسیاری از درخواست‌ها برای یک واکشی پس‌زمینه به شما امکان می‌دهد چیزهایی را که به طور منطقی برای کاربر یک چیز واحد هستند ترکیب کنید. برای مثال، یک فیلم ممکن است به 1000 منبع تقسیم شود (معمولاً با MPEG-DASH )، و با منابع اضافی مانند تصاویر همراه باشد. سطحی از یک بازی می تواند در بسیاری از منابع جاوا اسکریپت، تصویر و صدا پخش شود. اما برای کاربر، این فقط «فیلم» یا «سطح» است.

دریافت واکشی پس‌زمینه موجود

می‌توانید یک واکشی پس‌زمینه موجود مانند این دریافت کنید:

navigator.serviceWorker.ready.then(async (swReg) => {
  const bgFetch = await swReg.backgroundFetch.get('my-fetch');
});

…با پاس دادن شناسه واکشی پس‌زمینه مورد نظرتان. در صورتی که هیچ واکشی پس‌زمینه فعالی با آن شناسه وجود نداشته باشد، بازدهی undefined get .

واکشی پس‌زمینه از زمانی که ثبت می‌شود، تا زمانی که موفق شود، شکست بخورد یا سقط شود، «فعال» در نظر گرفته می‌شود.

با استفاده از getIds می توانید لیستی از تمام واکشی های پس زمینه فعال دریافت کنید:

navigator.serviceWorker.ready.then(async (swReg) => {
  const ids = await swReg.backgroundFetch.getIds();
});

ثبت‌های واکشی پس‌زمینه

BackgroundFetchRegistration ( bgFetch در مثال‌های بالا) دارای موارد زیر است:

خواص
id string
شناسه واکشی پس‌زمینه.
uploadTotal number
تعداد بایت هایی که باید به سرور ارسال شود.
uploaded number
تعداد بایت هایی که با موفقیت ارسال شد.
downloadTotal number
مقدار ارائه شده هنگام ثبت واکشی پس‌زمینه یا صفر.
downloaded number
تعداد بایت هایی که با موفقیت دریافت شد.

این مقدار ممکن است کاهش یابد. برای مثال، اگر اتصال قطع شود و دانلود از سر گرفته نشود، در این صورت مرورگر واکشی آن منبع را از ابتدا مجدداً راه اندازی می کند.

result

یکی از موارد زیر:

  • "" - واکشی پس‌زمینه فعال است، بنابراین هنوز نتیجه‌ای وجود ندارد.
  • "success" - واکشی پس زمینه موفقیت آمیز بود.
  • "failure" - واکشی پس زمینه انجام نشد. این مقدار فقط زمانی ظاهر می‌شود که واکشی پس‌زمینه کاملاً با شکست مواجه شود، زیرا در مرورگر نمی‌توان دوباره تلاش/ازسرگیری کرد.
failureReason

یکی از موارد زیر:

  • "" - واکشی پس‌زمینه شکست خورده است.
  • "aborted" - واکشی پس‌زمینه توسط کاربر لغو شد، یا abort() فراخوانی شد.
  • "bad-status" - یکی از پاسخ‌ها وضعیت خوب نداشت، مثلاً 404.
  • "fetch-error" - یکی از واکشی ها به دلایل دیگری مانند CORS، MIX، یک پاسخ جزئی نامعتبر، یا یک خطای شبکه عمومی برای واکشی که نمی توان دوباره امتحان کرد، ناموفق بود.
  • "quota-exceeded" - در طول واکشی پس‌زمینه به سهمیه فضای ذخیره‌سازی رسید.
  • "download-total-exceeded" - از "downloadTotal" ارائه شده بیشتر شد.
recordsAvailable boolean
آیا می توان به درخواست ها/پاسخ های اساسی دسترسی داشت؟

هنگامی که این match نادرست است و matchAll نمی تواند استفاده شود.

روش ها
abort() Returns Promise<boolean>
واکشی پس‌زمینه را لغو کنید.

در صورتی که واکشی با موفقیت لغو شود، قول برگشتی با true حل می شود.

matchAll(request, opts) Promise<Array<BackgroundFetchRecord>> را برمی گرداند
درخواست ها و پاسخ ها را دریافت کنید.

آرگومان‌های اینجا مانند API حافظه پنهان هستند. فراخوانی بدون آرگومان یک وعده برای همه رکوردها برمی گرداند.

برای جزئیات بیشتر به زیر مراجعه کنید.

match(request, opts) Promise<BackgroundFetchRecord> را برمی گرداند
همانطور که در بالا ذکر شد، اما با اولین مسابقه حل می شود.
رویدادها
progress هنگامی که هر یک از تغییرات uploaded ، downloaded ، result یا failureReason فعال می شود.

پیگیری پیشرفت

این را می توان از طریق رویداد progress انجام داد. به یاد داشته باشید که downloadTotal هر مقداری است که ارائه کرده‌اید، یا اگر مقداری ارائه نکرده‌اید 0 .

bgFetch.addEventListener('progress', () => {
  // If we didn't provide a total, we can't provide a %.
  if (!bgFetch.downloadTotal) return;

  const percent = Math.round(bgFetch.downloaded / bgFetch.downloadTotal * 100);
  console.log(`Download progress: ${percent}%`);
});

دریافت درخواست ها و پاسخ ها

bgFetch.match('/ep-5.mp3').then(async (record) => {
  if (!record) {
    console.log('No record found');
    return;
  }

  console.log(`Here's the request`, record.request);
  const response = await record.responseReady;
  console.log(`And here's the response`, response);
});

record یک BackgroundFetchRecord است و به شکل زیر است:

خواص
request Request
درخواستی که ارائه شد.
responseReady Promise<Response>
پاسخ واکشی شده

پاسخ پشت یک وعده است زیرا ممکن است هنوز دریافت نشده باشد. در صورت شکست واکشی، قول رد خواهد شد.

رویدادهای کارگر خدماتی

رویدادها
backgroundfetchsuccess همه چیز با موفقیت واکشی شد.
backgroundfetchfailure یک یا چند مورد واکشی ناموفق بود.
backgroundfetchabort یک یا چند واکشی ناموفق بود.

این فقط در صورتی مفید است که بخواهید داده های مرتبط را پاکسازی کنید.

backgroundfetchclick کاربر روی رابط کاربری پیشرفت دانلود کلیک کرد.

اشیاء رویداد دارای موارد زیر هستند:

خواص
registration BackgroundFetchRegistration
روش ها
updateUI({ title, icons }) به شما امکان می‌دهد عنوان/آیکون‌هایی را که در ابتدا تنظیم کرده‌اید تغییر دهید. این اختیاری است، اما به شما امکان می دهد در صورت لزوم، زمینه بیشتری را ارائه دهید. شما فقط می‌توانید *یکبار* این کار را در طول رویدادهای backgroundfetchsuccess و backgroundfetchfailure انجام دهید.

واکنش به موفقیت/شکست

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

اگر واکشی پس‌زمینه با موفقیت کامل شود، سرویس‌کار شما رویداد backgroundfetchsuccess را دریافت می‌کند و event.registration ثبت‌نام واکشی پس‌زمینه خواهد بود.

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

مانند بسیاری از رویدادهای Service Worker، از event.waitUntil استفاده کنید تا کارمند سرویس بداند که رویداد چه زمانی کامل شده است.

به عنوان مثال، در کارگر خدماتی شما:

addEventListener('backgroundfetchsuccess', (event) => {
  const bgFetch = event.registration;

  event.waitUntil(async function() {
    // Create/open a cache.
    const cache = await caches.open('downloads');
    // Get all the records.
    const records = await bgFetch.matchAll();
    // Copy each request/response across.
    const promises = records.map(async (record) => {
      const response = await record.responseReady;
      await cache.put(record.request, response);
    });

    // Wait for the copying to complete.
    await Promise.all(promises);

    // Update the progress notification.
    event.updateUI({ title: 'Episode 5 ready to listen!' });
  }());
});

ممکن است شکست به یک 404 کاهش یافته باشد، که ممکن است برای شما مهم نبوده باشد، بنابراین ممکن است ارزش آن را داشته باشد که برخی از پاسخ‌ها را مانند بالا در حافظه پنهان کپی کنید.

در حال واکنش به کلیک

رابط کاربری که پیشرفت و نتیجه دانلود را نشان می دهد قابل کلیک است. رویداد backgroundfetchclick در سرویس‌کار به شما امکان می‌دهد به این موضوع واکنش نشان دهید. همانطور که در بالا event.registration ثبت نام واکشی پس‌زمینه خواهد بود.

کار معمولی که با این رویداد انجام می شود باز کردن یک پنجره است:

addEventListener('backgroundfetchclick', (event) => {
  const bgFetch = event.registration;

  if (bgFetch.result === 'success') {
    clients.openWindow('/latest-podcasts');
  } else {
    clients.openWindow('/download-progress');
  }
});

منابع اضافی

تصحیح: نسخه قبلی این مقاله به اشتباه به Background Fetch به عنوان «استاندارد وب» اشاره کرده است. API در حال حاضر در مسیر استاندارد نیست، مشخصات را می توان در WICG به عنوان پیش نویس گزارش گروه جامعه یافت.