पेश है बैकग्राउंड में डेटा फ़ेच करने की सुविधा

हमने 2015 में बैकग्राउंड सिंक की सुविधा लॉन्च की थी. इससे सेवा वर्कर, तब तक काम को रोक सकता है, जब तक उपयोगकर्ता के पास इंटरनेट कनेक्शन नहीं होता. इसका मतलब है कि उपयोगकर्ता कोई मैसेज टाइप कर सकता है, 'भेजें' पर क्लिक कर सकता है, और साइट से बाहर निकल सकता है. ऐसा करने पर, मैसेज अब भेजा जाएगा या फिर तब भेजा जाएगा, जब इंटरनेट कनेक्शन उपलब्ध होगा.

यह एक काम की सुविधा है. हालांकि, इसके लिए ज़रूरी है कि फ़ेच करने के दौरान, सेवा वर्कर चालू रहे. मैसेज भेजने जैसे छोटे कामों के लिए, यह कोई समस्या नहीं है. हालांकि, अगर टास्क पूरा होने में बहुत ज़्यादा समय लगता है, तो ब्राउज़र सेवा वर्कर को बंद कर देगा. ऐसा न करने पर, उपयोगकर्ता की निजता और बैटरी को खतरा हो सकता है.

अगर आपको कोई ऐसा कॉन्टेंट डाउनलोड करना है जिसमें ज़्यादा समय लग सकता है, तो क्या करें? जैसे, कोई मूवी, पॉडकास्ट या गेम के लेवल. इसके लिए, बैकग्राउंड फ़ेच की सुविधा है.

बैकग्राउंड फ़ेच करने की सुविधा, Chrome के 74 वर्शन से डिफ़ॉल्ट रूप से उपलब्ध है.

यहां दो मिनट का एक छोटा डेमो दिया गया है. इसमें, बैकग्राउंड फ़ेच की सुविधा का इस्तेमाल करने से पहले और बाद की परफ़ॉर्मेंस की तुलना की गई है:

खुद डेमो आज़माएं और कोड ब्राउज़ करें.

यह कैसे काम करता है

बैकग्राउंड फ़ेच इस तरह काम करता है:

  1. ब्राउज़र को बैकग्राउंड में फ़ेच करने का ग्रुप बनाने के लिए कहा जाता है.
  2. ब्राउज़र उन चीज़ों को फ़ेच करता है और उपयोगकर्ता को प्रोग्रेस दिखाता है.
  3. फ़ेच पूरा होने या पूरा न होने पर, ब्राउज़र आपका सेवा वर्कर खोलता है और आपको बताने के लिए कोई इवेंट ट्रिगर करता है कि क्या हुआ. यहां आपको यह तय करना होता है कि जवाबों का क्या करना है.

अगर उपयोगकर्ता पहले चरण के बाद आपकी साइट के पेजों को बंद कर देता है, तो कोई बात नहीं, डाउनलोड जारी रहेगा. फ़ेच की जानकारी साफ़ तौर पर दिखती है और इसे आसानी से रोका जा सकता है. इसलिए, बैकग्राउंड में सिंक करने वाले टास्क के बहुत ज़्यादा समय तक चलने की वजह से निजता से जुड़ी कोई समस्या नहीं होती. सेवा वर्कर लगातार नहीं चलता है. इसलिए, इस बात की चिंता नहीं होती कि वह सिस्टम का गलत इस्तेमाल कर सकता है. जैसे, बैकग्राउंड में बिटकॉइन माइनिंग करना.

कुछ प्लैटफ़ॉर्म (जैसे, Android) पर, पहले चरण के बाद ब्राउज़र बंद हो सकता है. ऐसा इसलिए होता है, क्योंकि ब्राउज़र, फ़ेच करने की प्रोसेस को ऑपरेटिंग सिस्टम को सौंप सकता है.

अगर उपयोगकर्ता ऑफ़लाइन होने पर डाउनलोड शुरू करता है या डाउनलोड के दौरान ऑफ़लाइन हो जाता है, तो बैकग्राउंड में फ़ेच करने की प्रोसेस रोक दी जाएगी और बाद में फिर से शुरू की जाएगी.

एपीआई

सुविधा का पता लगाना

किसी भी नई सुविधा की तरह, आपको यह पता लगाना होगा कि ब्राउज़र पर यह सुविधा काम करती है या नहीं. बैकग्राउंड फ़ेच के लिए, यह उतना ही आसान है जितना:

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

बैकग्राउंड फ़ेच शुरू करना

मुख्य एपीआई, सर्विस वर्कर रजिस्ट्रेशन पर निर्भर करता है. इसलिए, पक्का करें कि आपने पहले सर्विस वर्कर रजिस्टर किया हो. इसके बाद:

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>
फ़ेच की जाने वाली चीज़ें. स्ट्रिंग को यूआरएल माना जाएगा और new Request(theString) की मदद से, उन्हें Request में बदल दिया जाएगा.

दूसरे ऑरिजिन से चीज़ें तब तक फ़ेच की जा सकती हैं, जब तक रिसॉर्स, CORS के ज़रिए ऐसा करने की अनुमति देते हैं.

ध्यान दें: फ़िलहाल, Chrome उन अनुरोधों के साथ काम नहीं करता जिनके लिए सीओआरएस प्रीफ़्लाइट की ज़रूरत होती है.

options ऐसा ऑब्जेक्ट जिसमें ये चीज़ें शामिल हो सकती हैं:
options.title string
ब्राउज़र के लिए एक टाइटल, जो प्रोग्रेस के साथ दिखेगा.
options.icons Array<IconDefinition>
`src`, `size`, और `type` एट्रिब्यूट वाले ऑब्जेक्ट का कलेक्शन.
options.downloadTotal number
रिस्पॉन्स बॉडी का कुल साइज़ (अन-ज़िप किए जाने के बाद).

हालांकि, यह जानकारी देना ज़रूरी नहीं है, लेकिन हमारा सुझाव है कि आप इसे दें. इसका इस्तेमाल, उपयोगकर्ता को यह बताने के लिए किया जाता है कि डाउनलोड कितना बड़ा है. साथ ही, डाउनलोड की स्थिति की जानकारी भी दी जाती है. अगर आपने साइज़ की जानकारी नहीं दी है, तो ब्राउज़र उपयोगकर्ता को बताएगा कि साइज़ की जानकारी नहीं है. इस वजह से, उपयोगकर्ता के डाउनलोड को रद्द करने की संभावना ज़्यादा हो सकती है.

अगर बैकग्राउंड फ़ेच की मदद से डाउनलोड किए गए आइटम की संख्या, यहां दी गई संख्या से ज़्यादा हो जाती है, तो डाउनलोड की प्रोसेस को रोक दिया जाएगा. अगर डाउनलोड किए गए डेटा का साइज़ downloadTotal से कम है, तो यह पूरी तरह से ठीक है. इसलिए, अगर आपको यकीन नहीं है कि डाउनलोड किए गए डेटा का साइज़ कितना होगा, तो बेहतर होगा कि आप ज़्यादा से ज़्यादा डेटा डाउनलोड करें.

backgroundFetch.fetch एक प्रॉमिस दिखाता है, जो BackgroundFetchRegistration के साथ रिज़ॉल्व होता है. इस बारे में हम बाद में बताएंगे. अगर उपयोगकर्ता ने डाउनलोड करने की सुविधा से ऑप्ट आउट किया है या दिए गए पैरामीटर में से कोई एक अमान्य है, तो प्रॉमिस अस्वीकार कर दिया जाता है.

एक ही बैकग्राउंड फ़ेच के लिए कई अनुरोध करने से, उन चीज़ों को जोड़ा जा सकता है जो उपयोगकर्ता के लिए एक ही चीज़ हैं. उदाहरण के लिए, किसी मूवी को हज़ारों संसाधनों में बांटा जा सकता है. आम तौर पर, ऐसा MPEG-DASH के साथ होता है. साथ ही, इसमें इमेज जैसे अन्य संसाधन भी शामिल हो सकते हैं. किसी गेम का लेवल, कई JavaScript, इमेज, और ऑडियो रिसॉर्स में हो सकता है. हालांकि, उपयोगकर्ता के लिए यह सिर्फ़ "फ़िल्म" या "लेवल" है.

बैकग्राउंड में फ़ेच की जा रही किसी मौजूदा फ़ीड की जानकारी पाना

बैकग्राउंड में फ़ेच की जा रही किसी मौजूदा फ़ाइल को इस तरह देखा जा सकता है:

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

…जिस बैकग्राउंड फ़ेच का आपको इस्तेमाल करना है उसका id पास करके. अगर उस आईडी के साथ कोई बैकग्राउंड फ़ेच ऐक्टिव नहीं है, तो get undefined दिखाता है.

बैकग्राउंड फ़ेच को रजिस्टर होने के बाद से, तब तक "चालू" माना जाता है, जब तक वह पूरा नहीं हो जाता, पूरा नहीं होता या उसे रोका नहीं जाता.

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" - किसी फ़ेच को किसी दूसरी वजह से फ़ेच नहीं किया जा सका. जैसे, सीओआरएस, एमआईएक्स, कुछ हिस्से का अमान्य जवाब या फ़ेच करने के लिए नेटवर्क की सामान्य गड़बड़ी, जिसे फिर से आज़माया नहीं जा सकता.
  • "quota-exceeded" - बैकग्राउंड में फ़ेच करने के दौरान, स्टोरेज कोटा की सीमा पूरी हो गई.
  • "download-total-exceeded" - दिए गए `downloadTotal` की वैल्यू, तय सीमा से ज़्यादा है.
recordsAvailable boolean
क्या मौजूदा अनुरोधों/जवाबों को ऐक्सेस किया जा सकता है?

इस फ़ील्ड की वैल्यू 'गलत' होने पर, match और matchAll का इस्तेमाल नहीं किया जा सकता.

तरीके
abort() Promise<boolean>
बैकग्राउंड फ़ेच को बंद करने पर यह वैल्यू दिखती है.

अगर फ़ेच को सही तरीके से रोका गया, तो रिटर्न किया गया प्रॉमिस 'सही' के तौर पर हल होता है.

matchAll(request, opts) Promise<Array<BackgroundFetchRecord>>
अनुरोध और जवाब पाएं.

यहां दिए गए आर्ग्युमेंट, कैश मेमोरी एपीआई के आर्ग्युमेंट जैसे ही हैं. बिना आर्ग्युमेंट के कॉल करने पर, सभी रिकॉर्ड के लिए एक प्रॉमिस मिलता है.

ज़्यादा जानकारी के लिए नीचे देखें.

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 बैकग्राउंड फ़ेच रजिस्ट्रेशन होगा.

इस इवेंट के बाद, फ़ेच किए गए अनुरोधों और जवाबों को ऐक्सेस नहीं किया जा सकता. इसलिए, अगर आपको उन्हें सेव रखना है, तो उन्हें कैश मेमोरी एपीआई जैसी किसी जगह पर ले जाएं.

ज़्यादातर सेवा वर्कर इवेंट की तरह, 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');
  }
});

अन्य संसाधन

सुधार: इस लेख के पिछले वर्शन में, बैकग्राउंड फ़ेच को "वेब स्टैंडर्ड" के तौर पर गलत तरीके से बताया गया था. फ़िलहाल, यह एपीआई स्टैंडर्ड ट्रैक पर नहीं है. इसकी जानकारी, WICG में ड्राफ़्ट कम्यूनिटी ग्रुप रिपोर्ट के तौर पर देखी जा सकती है.