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

हमने 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>
As above, but resolves with the first match.
इवेंट
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 में ड्राफ़्ट कम्यूनिटी ग्रुप रिपोर्ट के तौर पर देखा जा सकता है.