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

जेफ़ पॉस्निक
जेफ़ पॉस्निक

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

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

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

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});
}