उपलब्ध स्टोरेज के लिए बची जगह का अनुमान लगाना

tl;dr

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

if ('storage' in navigator && 'estimate' in navigator.storage) {
  navigator.storage.estimate().then(({usage, quota}) => {
    console.log(`Using ${usage} out of ${quota} bytes.`);
  });
}

आधुनिक वेब ऐप्लिकेशन और डेटा स्टोरेज

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

पहला टाइप का डेटा, आपके वेब ऐप्लिकेशन को लोड करने के लिए ज़रूरी होता है. इसमें एचटीएमएल, JavaScript, सीएसएस, और शायद कुछ इमेज शामिल होती हैं. सेवा वर्कर और कैश मेमोरी स्टोरेज एपीआई, उन मुख्य संसाधनों को सेव करने के लिए ज़रूरी इंफ़्रास्ट्रक्चर उपलब्ध कराते हैं. इसके बाद, वेब ऐप्लिकेशन को तेज़ी से लोड करने के लिए, बाद में उनका इस्तेमाल किया जाता है. ऐसा करने से, नेटवर्क का इस्तेमाल कम से कम किया जाता है. (आपके वेब ऐप्लिकेशन की बिल्ड प्रोसेस के साथ इंटिग्रेट होने वाले टूल, जैसे कि नई Workbox लाइब्रेरी या पुरानी sw-precache, इस तरह के डेटा को सेव करने, अपडेट करने, और इस्तेमाल करने की प्रोसेस को पूरी तरह से ऑटोमेट कर सकते हैं.)

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

पिछले: window.webkitStorageInfo और navigator.webkitTemporaryStorage

ब्राउज़र, पहले से तय किए गए इंटरफ़ेस की मदद से, इस तरह के इंट्रोस्पेक्शन की सुविधा देते रहे हैं. जैसे, बहुत पुराना (और अब काम नहीं करने वाला) window.webkitStorageInfo और ज़्यादा पुराना नहीं, लेकिन अब भी स्टैंडर्ड नहीं navigator.webkitTemporaryStorage. इन इंटरफ़ेस से काम की जानकारी मिलती थी, लेकिन वे वेब स्टैंडर्ड के तौर पर आगे नहीं बढ़ सकते.

यहीं WHATWG स्टोरेज स्टैंडर्ड का इस्तेमाल किया जाता है.

आने वाला समय: navigator.storage

स्टोरेज के लिए लाइव स्टैंडर्ड पर चल रहे काम के तहत, कुछ काम के एपीआई को StorageManager इंटरफ़ेस में शामिल किया गया है. इसे ब्राउज़र पर navigator.storage के तौर पर दिखाया जाता है. कई अन्य नए वेब एपीआई की तरह, navigator.storage सिर्फ़ सुरक्षित ऑरिजिन पर उपलब्ध है. इन ऑरिजिन को एचटीटीपीएस या localhost के ज़रिए दिखाया जाता है.

पिछले साल, हमने navigator.storage.persist() वाला तरीका पेश किया था. इसकी मदद से, आपके वेब ऐप्लिकेशन को स्टोरेज को अपने-आप खाली करने की सुविधा से छूट पाने का अनुरोध करने की सुविधा मिलती है.

अब इसमें navigator.storage.estimate() तरीका भी शामिल है, जो navigator.webkitTemporaryStorage.queryUsageAndQuota() के लिए एक आधुनिक विकल्प के तौर पर काम करता है. estimate() भी मिलती-जुलती जानकारी दिखाता है. हालांकि, यह वाद पर आधारित इंटरफ़ेस दिखाता है. यह इंटरफ़ेस, असाइनिमेंट के पूरा होने का इंतज़ार किए बिना, एक से ज़्यादा टास्क को एक साथ पूरा करने की सुविधा देने वाले दूसरे आधुनिक एपीआई के हिसाब से होता है. estimate() से मिलने वाला प्रॉमिस, एक ऑब्जेक्ट के साथ रिज़ॉल्व होता है. इस ऑब्जेक्ट में दो प्रॉपर्टी होती हैं: usage, जो फ़िलहाल इस्तेमाल किए जा रहे बाइट की संख्या दिखाती है और quota, जो मौजूदा ऑरिजिन से स्टोर किए जा सकने वाले ज़्यादा से ज़्यादा बाइट दिखाती है. (स्टोरेज से जुड़ी हर चीज़ की तरह, कोटा पूरे ऑरिजिन पर लागू होता है.)

अगर कोई वेब ऐप्लिकेशन, IndexedDB या Cache Storage API जैसे टूल का इस्तेमाल करके, किसी ऑरिजिन के उपलब्ध कोटे से ज़्यादा डेटा सेव करने की कोशिश करता है, तो अनुरोध QuotaExceededError अपवाद के साथ पूरा नहीं होगा.

स्टोरेज के अनुमान की सुविधा

estimate() का इस्तेमाल कैसे किया जाए, यह इस बात पर निर्भर करता है कि आपके ऐप्लिकेशन को किस तरह के डेटा को सेव करना है. उदाहरण के लिए, अपने इंटरफ़ेस में किसी कंट्रोल को अपडेट करके, उपयोगकर्ताओं को यह जानकारी दी जा सकती है कि स्टोरेज से जुड़ा हर काम पूरा होने के बाद, कितना स्टोरेज इस्तेमाल किया जा रहा है. इसके बाद, आपको एक ऐसा इंटरफ़ेस उपलब्ध कराना चाहिए जिससे उपयोगकर्ता, ज़रूरत न पड़ने वाले डेटा को मैन्युअल तरीके से मिटा सकें. आपके पास इस तरह का कोड लिखने का विकल्प है:

// For a primer on async/await, see
// https://developers.google.com/web/fundamentals/getting-started/primers/async-functions
async function storeDataAndUpdateUI(dataUrl) {
  // Pro-tip: The Cache Storage API is available outside of service workers!
  // See https://googlechrome.github.io/samples/service-worker/window-caches/
  const cache = await caches.open('data-cache');
  await cache.add(dataUrl);

  if ('storage' in navigator && 'estimate' in navigator.storage) {
    const {usage, quota} = await navigator.storage.estimate();
    const percentUsed = Math.round(usage / quota * 100);
    const usageInMib = Math.round(usage / (1024 * 1024));
    const quotaInMib = Math.round(quota / (1024 * 1024));

    const details = `${usageInMib} out of ${quotaInMib} MiB used (${percentUsed}%)`;

    // This assumes there's a <span id="storageEstimate"> or similar on the page.
    document.querySelector('#storageEstimate').innerText = details;
  }
}

अनुमान कितना सटीक है?

यह बात ध्यान में रखना मुश्किल नहीं है कि फ़ंक्शन से मिलने वाला डेटा, किसी ऑरिजिन के इस्तेमाल किए जा रहे स्टोरेज का सिर्फ़ अनुमान होता है. यह फ़ंक्शन के नाम में ही मौजूद है! usage और quota, दोनों वैल्यू स्थिर नहीं होतीं. इसलिए, हमारा सुझाव है कि आप इन बातों का ध्यान रखें:

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

फ़िलहाल: सुविधा का पता लगाने और फ़ॉलबैक

estimate(), Chrome 61 से डिफ़ॉल्ट रूप से चालू होता है. Firefox, navigator.storage के साथ प्रयोग कर रहा है. हालांकि, अगस्त 2017 तक, यह डिफ़ॉल्ट रूप से चालू नहीं है. इसकी जांच करने के लिए, आपको dom.storageManager.enabled प्राथमिकता को चालू करना होगा.

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

function storageEstimateWrapper() {
  if ('storage' in navigator && 'estimate' in navigator.storage) {
    // We've got the real thing! Return its response.
    return navigator.storage.estimate();
  }

  if ('webkitTemporaryStorage' in navigator &&
      'queryUsageAndQuota' in navigator.webkitTemporaryStorage) {
    // Return a promise-based wrapper that will follow the expected interface.
    return new Promise(function(resolve, reject) {
      navigator.webkitTemporaryStorage.queryUsageAndQuota(
        function(usage, quota) {resolve({usage: usage, quota: quota})},
        reject
      );
    });
  }

  // If we can't estimate the values, return a Promise that resolves with NaN.
  return Promise.resolve({usage: NaN, quota: NaN});
}