अपने ऐप्लिकेशन का डेटा ऑफ़लाइन उपलब्ध कराने के लिए, Cache API का इस्तेमाल करने का तरीका जानें.
Cache API, नेटवर्क के अनुरोधों और उनसे जुड़े रिस्पॉन्स को सेव और फिर से पाने का सिस्टम है. ये आपके ऐप्लिकेशन को चलाने के दौरान, सामान्य अनुरोध और जवाब हो सकते हैं. इसके अलावा, इन्हें सिर्फ़ बाद में इस्तेमाल करने के लिए डेटा सेव करने के मकसद से भी बनाया जा सकता है.
Cache API को इसलिए बनाया गया था, ताकि सेवा वर्कर नेटवर्क अनुरोधों को कैश मेमोरी में सेव कर सकें. इससे, नेटवर्क की स्पीड या उपलब्धता के बावजूद, तेज़ी से जवाब दिए जा सकते हैं. हालांकि, इस एपीआई का इस्तेमाल सामान्य स्टोरेज तरीके के तौर पर भी किया जा सकता है.
YouTube TV कहां उपलब्ध है?
कैश एपीआई सभी मॉडर्न ब्राउज़र में उपलब्ध है. इसे ग्लोबल caches
प्रॉपर्टी के ज़रिए एक्सपोज़ किया जाता है, ताकि किसी सुविधा का पता लगाने के लिए एपीआई की मौजूदगी की जांच की जा सके:
const cacheAvailable = 'caches' in self;
कैश एपीआई को किसी विंडो, iframe, वर्कर या सर्विस वर्कर से ऐक्सेस किया जा सकता है.
क्या-क्या सेव किया जा सकता है
कैश मेमोरी में सिर्फ़ Request
और
Response
ऑब्जेक्ट के पेयर सेव किए जाते हैं. ये ऑब्जेक्ट, HTTP अनुरोधों और रिस्पॉन्स को दिखाते हैं. हालांकि, अनुरोधों और जवाबों में ऐसा कोई भी डेटा शामिल हो सकता है
जिसे एचटीटीपी पर ट्रांसफ़र किया जा सके.
कितना संग्रहित किया जा सकता है?
कम शब्दों में कहें, तो काफ़ी, कम से कम दो सौ मेगाबाइट और संभावित रूप से सैकड़ों गीगाबाइट या उससे ज़्यादा. ब्राउज़र के लागू होने का तरीका अलग-अलग होता है. हालांकि, आम तौर पर उपलब्ध स्टोरेज की मात्रा, डिवाइस में उपलब्ध स्टोरेज की मात्रा पर निर्भर करती है.
कैश मेमोरी बनाना और उसे खोलना
कैश मेमोरी खोलने के लिए, caches.open(name)
तरीके का इस्तेमाल करें. इसके लिए, कैश मेमोरी के नाम को एक पैरामीटर के तौर पर पास करें. अगर नाम वाली कैश मेमोरी मौजूद नहीं है, तो इसे बनाया जाता है. इस तरीके से Promise
नतीजा मिलता है, जो Cache
ऑब्जेक्ट के साथ रिज़ॉल्व हो जाता है.
const cache = await caches.open('my-cache');
// do something with cache...
कैश मेमोरी में जोड़ना
कैश मेमोरी में आइटम जोड़ने के तीन तरीके हैं - add
, addAll
, और put
.
तीनों तरीके, Promise
दिखाते हैं.
cache.add
सबसे पहले, cache.add()
है. यह एक पैरामीटर लेता है, या तो Request
या यूआरएल (string
). यह नेटवर्क से अनुरोध करता है और रिस्पॉन्स को कैश मेमोरी में सेव करता है. अगर फ़ेच करने में कोई गड़बड़ी होती है या जवाब का स्टेटस कोड 200 की रेंज में नहीं होता है, तो कुछ भी सेव नहीं किया जाता और Promise
अस्वीकार कर दिया जाता है. ध्यान दें कि क्रॉस-ऑरिजिन वाले ऐसे अनुरोध सेव नहीं किए जा सकते जो सीओआरएस मोड में नहीं हैं, क्योंकि वे 0
का status
दिखाते हैं. इस तरह के अनुरोधों को सिर्फ़ put
के साथ सेव किया जा सकता है.
// Retreive data.json from the server and store the response.
cache.add(new Request('/data.json'));
// Retreive data.json from the server and store the response.
cache.add('/data.json');
cache.addAll
अगला मैसेज cache.addAll()
ने भेजा है। यह add()
की तरह ही काम करता है. हालांकि, यह Request
ऑब्जेक्ट या यूआरएल (string
) की एक कलेक्शन लेता है. यह हर अनुरोध के लिए cache.add
को कॉल करने की तरह ही काम करता है. हालांकि, अगर कोई अनुरोध कैश मेमोरी में सेव नहीं है, तो Promise
उसे अस्वीकार कर देता है.
const urls = ['/weather/today.json', '/weather/tomorrow.json'];
cache.addAll(urls);
इनमें से हर मामले में, कोई नई एंट्री, मैच होने वाली किसी भी मौजूदा एंट्री को ओवरराइट कर देती है. इसमें, प्रॉपर्टी वापस पाने वाले सेक्शन में बताए गए मैच करने के उन नियमों का इस्तेमाल किया जाता है.
cache.put
आखिर में, cache.put()
की मदद से नेटवर्क से मिले रिस्पॉन्स को सेव किया जा सकता है या अपना Response
बनाया और सेव किया जा सकता है. इसके लिए दो
पैरामीटर की ज़रूरत होती है. पहला, Request
ऑब्जेक्ट या यूआरएल (string
) हो सकता है.
दूसरा, नेटवर्क से मिला Response
या आपके कोड से जनरेट किया गया Response
होना चाहिए.
// Retrieve data.json from the server and store the response.
cache.put('/data.json');
// Create a new entry for test.json and store the newly created response.
cache.put('/test.json', new Response('{"foo": "bar"}'));
// Retrieve data.json from the 3rd party site and store the response.
cache.put('https://example.com/data.json');
put()
तरीका, add()
या addAll()
से ज़्यादा अनुमति देता है. साथ ही, इससे आपको ऐसे रिस्पॉन्स स्टोर करने की अनुमति मिलती है जो CORS के दायरे में नहीं आते या जिनका स्टेटस कोड 200 रेंज में नहीं होता. इससे, उसी अनुरोध के लिए मिले सभी पिछले जवाब ओवरराइट हो जाएंगे.
अनुरोध ऑब्जेक्ट बनाना
सेव की जा रही चीज़ के यूआरएल का इस्तेमाल करके, Request
ऑब्जेक्ट बनाएं:
const request = new Request('/my-data-store/item-id');
Response ऑब्जेक्ट के साथ काम करना
Response
ऑब्जेक्ट कन्स्ट्रक्टर कई तरह के डेटा को स्वीकार करता है. इनमें Blob
, ArrayBuffer
, FormData
ऑब्जेक्ट, और स्ट्रिंग शामिल हैं.
const imageBlob = new Blob([data], {type: 'image/jpeg'});
const imageResponse = new Response(imageBlob);
const stringResponse = new Response('Hello world');
सही हेडर सेट करके, Response
का MIME टाइप सेट किया जा सकता है.
const options = {
headers: {
'Content-Type': 'application/json'
}
}
const jsonResponse = new Response('{}', options);
अगर आपने Response
को वापस पा लिया है और आपको इसका मुख्य हिस्सा ऐक्सेस करना है, तो इसे इस्तेमाल करने के कई तरीके हैं. हर नतीजा एक Promise
दिखाता है,
जिसकी वैल्यू अलग तरह की होती है.
तरीका | ब्यौरा |
---|---|
arrayBuffer |
बाइट में सीरियलाइज़ किए गए मुख्य हिस्से वाले ArrayBuffer को दिखाता है.
|
blob |
Blob दिखाता है. अगर Response को Blob से बनाया गया था, तो इस नए Blob का टाइप भी वही होगा. ऐसा न करने पर, Response के Content-Type का इस्तेमाल किया जाता है.
|
text |
मुख्य हिस्से के बाइट को UTF-8 कोड में बदली गई स्ट्रिंग के तौर पर समझता है. |
json |
बॉडी के बाइट को UTF-8 एन्कोड की गई स्ट्रिंग के तौर पर समझता है. इसके बाद, इसे JSON के तौर पर पार्स करने की कोशिश करता है. नतीजे के तौर पर मिलने वाला ऑब्जेक्ट लौटाता है या अगर स्ट्रिंग को JSON के रूप में पार्स नहीं किया जा सकता, तो
TypeError दिखाता है.
|
formData |
यह बॉडी के बाइट को एचटीएमएल फ़ॉर्म के तौर पर देखता है. इसे multipart/form-data या application/x-www-form-urlencoded के तौर पर एन्कोड किया जाता है. यह एक
FormData
ऑब्जेक्ट दिखाता है. अगर डेटा को पार्स नहीं किया जा सकता, तो यह TypeError दिखाता है.
|
body |
यह फ़ंक्शन बॉडी के डेटा के लिए ReadableStream दिखाता है. |
उदाहरण के लिए
const response = new Response('Hello world');
const buffer = await response.arrayBuffer();
console.log(new Uint8Array(buffer));
// Uint8Array(11) [72, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100]
कैश मेमोरी से डेटा वापस पाना
कैश मेमोरी में किसी आइटम को ढूंढने के लिए, match
तरीके का इस्तेमाल किया जा सकता है.
const response = await cache.match(request);
console.log(request, response);
अगर request
कोई स्ट्रिंग है, तो ब्राउज़र new Request(request)
को कॉल करके उसे Request
में बदल देता है. कोई मिलती-जुलती एंट्री मिलने पर फ़ंक्शन, Promise
दिखाता है जो Response
के बराबर होता है या नहीं होने पर undefined
दिखाता है.
दो Requests
मैच करते हैं या नहीं, यह तय करने के लिए ब्राउज़र सिर्फ़ यूआरएल का इस्तेमाल नहीं करता. अगर दो अनुरोधों में अलग-अलग क्वेरी स्ट्रिंग, Vary
हेडर या एचटीटीपी के तरीके (GET
, POST
, PUT
वगैरह) हैं, तो उन्हें अलग माना जाता है.
इनमें से कुछ या सभी चीज़ों को अनदेखा किया जा सकता है. इसके लिए, दूसरे पैरामीटर के तौर पर विकल्प ऑब्जेक्ट पास करें.
const options = {
ignoreSearch: true,
ignoreMethod: true,
ignoreVary: true
};
const response = await cache.match(request, options);
// do something with the response
अगर कैश मेमोरी में सेव किए गए एक से ज़्यादा अनुरोध मैच करते हैं, तो सबसे पहले बनाए गए अनुरोध को दिखाया जाता है. अगर आपको खोज के नतीजों से मिलते-जुलते सभी जवाबों को वापस पाना है, तो cache.matchAll()
का इस्तेमाल करें.
const options = {
ignoreSearch: true,
ignoreMethod: true,
ignoreVary: true
};
const responses = await cache.matchAll(request, options);
console.log(`There are ${responses.length} matching responses.`);
शॉर्टकट के तौर पर, सभी कैश मेमोरी को एक साथ खोजा जा सकता है. इसके लिए, हर कैश मेमोरी के लिए cache.match()
को कॉल करने के बजाय, caches.match()
का इस्तेमाल करें.
खोजा जा रहा है
Cache API, अनुरोधों या रिस्पॉन्स को खोजने का कोई तरीका नहीं देता. हालांकि, Response
ऑब्जेक्ट से मैच करने वाली एंट्री को खोजा जा सकता है. हालांकि, फ़िल्टर का इस्तेमाल करके या इंडेक्स बनाकर, अपनी खोज की सुविधा लागू की जा सकती है.
फ़िल्टर करना
अपनी खोज को लागू करने का एक तरीका यह है कि आप सभी एंट्री को दोहराएं और अपनी पसंद की
खोजों को फ़िल्टर करें. मान लें कि आपको वे सभी आइटम खोजने हैं जिनके यूआरएल
.png
पर खत्म होते हैं.
async function findImages() {
// Get a list of all of the caches for this origin
const cacheNames = await caches.keys();
const result = [];
for (const name of cacheNames) {
// Open the cache
const cache = await caches.open(name);
// Get a list of entries. Each item is a Request object
for (const request of await cache.keys()) {
// If the request URL matches, add the response to the result
if (request.url.endsWith('.png')) {
result.push(await cache.match(request));
}
}
}
return result;
}
इस तरह, एंट्री को फ़िल्टर करने के लिए, Request
और Response
ऑब्जेक्ट की किसी भी प्रॉपर्टी का इस्तेमाल किया जा सकता है. ध्यान दें कि अगर डेटा के बड़े सेट पर
खोज की जाती है, तो यह प्रोसेस धीमी होती है.
इंडेक्स बनाना
अपनी खोज को लागू करने का दूसरा तरीका यह है कि आप उन एंट्री का अलग इंडेक्स बनाएं जिन्हें खोजा जा सकता है और इंडेक्स को IndexedDB में सेव किया जा सकता है. IndexedDB को इस तरह के ऑपरेशन के लिए डिज़ाइन किया गया है. इसलिए, बड़ी संख्या में एंट्री के साथ इसकी परफ़ॉर्मेंस बेहतर होती है.
अगर खोजी जा सकने वाली प्रॉपर्टी के साथ-साथ Request
का यूआरएल भी सेव किया जाता है, तो खोज करने के बाद सही कैश मेमोरी एंट्री को आसानी से वापस पाया जा सकता है.
किसी आइटम को मिटाना
कैश मेमोरी से किसी आइटम को मिटाने के लिए:
cache.delete(request);
जहां अनुरोध, Request
या यूआरएल स्ट्रिंग हो सकता है. इस तरीके में, cache.match
वाले विकल्प ऑब्जेक्ट का भी इस्तेमाल किया जाता है. इससे आपको एक ही यूआरएल के कई Request
/Response
पेयर मिटाए जा सकते हैं.
cache.delete('/example/file.txt', {ignoreVary: true, ignoreSearch: true});
कैश मेमोरी मिटाना
कैश मेमोरी मिटाने के लिए, caches.delete(name)
पर कॉल करें. यह फ़ंक्शन एक Promise
दिखाता है. अगर कैश मेमोरी मौजूद थी और उसे मिटा दिया गया था, तो यह true
पर सेट हो जाता है. अगर कैश मेमोरी मौजूद नहीं थी, तो यह false
पर सेट हो जाता है.
धन्यवाद
इस लेख का मूल वर्शन लिखने वाले मैट स्केल को धन्यवाद. यह लेख पहली बार WebFundamentals पर पब्लिश हुआ था.