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

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

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

पिछली यादें: window.webkitStorageInfo और navigator.webkitTemporaryStorage

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

यहां से WhatWG Storage Standard इमेज की इमेज अपलोड की जाती है.

आने वाले समय की जानकारी: navigator.storage

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

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

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

अगर कोई वेब ऐप्लिकेशन, IndexedDB या कैश स्टोरेज एपीआई जैसे डेटा को स्टोर करने की कोशिश करता है, जो किसी दिए गए ऑरिजिन को उसके उपलब्ध कोटा पर लाने के लिए काफ़ी है, तो अनुरोध 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 से पता चलता है कि ऑरिजिन के लिए फ़िलहाल कितना स्टोरेज बचा है. यह वैल्यू, कुछ चीज़ों पर निर्भर करती है, जैसे कि डिवाइस का कुल स्टोरेज. हालांकि, कुछ चीज़ों की वजह से भी स्टोरेज में उतार-चढ़ाव हो सकता है. जैसे, स्टोरेज में कितनी जगह खाली नहीं है. इसलिए जब किसी डिवाइस पर मौजूद अन्य ऐप्लिकेशन डेटा लिखते या मिटाते हैं, तो हो सकता है कि ब्राउज़र आपके वेब ऐप्लिकेशन के ऑरिजिन के लिए इस्तेमाल किए जाने वाले स्पेस को बदल दे.

मौजूद है: सुविधा की पहचान और फ़ॉलबैक

Chrome 61 और उसके बाद के वर्शन में, estimate() डिफ़ॉल्ट रूप से चालू होता है. 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});
}