تخمین فضای ذخیره سازی موجود

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

برنامه های وب مدرن و ذخیره سازی داده ها

وقتی به نیازهای ذخیره سازی یک برنامه وب مدرن فکر می کنید، به تقسیم آنچه ذخیره می شود به دو دسته کمک می کند: داده های اصلی مورد نیاز برای بارگیری برنامه وب و داده های مورد نیاز برای تعامل معنی دار با کاربر پس از بارگیری برنامه.

اولین نوع داده، آنچه برای بارگذاری برنامه وب شما نیاز است، شامل HTML، جاوا اسکریپت، CSS و شاید برخی از تصاویر است. کارکنان سرویس ، همراه با API حافظه کش ، زیرساخت های مورد نیاز را برای ذخیره آن منابع اصلی و سپس استفاده از آنها برای بارگیری سریع برنامه وب شما، به طور ایده آل، دور زدن شبکه را فراهم می کنند. (ابزارهایی که با فرآیند ساخت برنامه وب شما یکپارچه می شوند، مانند کتابخانه های Workbox جدید یا sw-precache قدیمی تر، می توانند فرآیند ذخیره، به روز رسانی و استفاده از این نوع داده ها را کاملاً خودکار کنند.)

اما نوع دیگر داده ها چطور؟ اینها منابعی هستند که برای بارگیری برنامه وب شما مورد نیاز نیستند، اما ممکن است نقش مهمی در تجربه کاربری کلی شما داشته باشند. به عنوان مثال، اگر در حال نوشتن یک برنامه وب ویرایش تصویر هستید، ممکن است بخواهید یک یا چند نسخه محلی از یک تصویر را ذخیره کنید و به کاربران اجازه دهید بین ویرایش‌ها جابجا شوند و کار خود را لغو کنند. یا اگر در حال توسعه تجربه پخش رسانه آفلاین هستید، ذخیره فایل های صوتی یا تصویری به صورت محلی یک ویژگی حیاتی خواهد بود. هر برنامه وب که می‌تواند شخصی‌سازی شود در نهایت نیاز به ذخیره نوعی اطلاعات وضعیت دارد. چگونه می دانید چه مقدار فضای برای این نوع ذخیره سازی زمان اجرا در دسترس است و وقتی فضای خالی شما تمام شود چه اتفاقی می افتد؟

گذشته: window.webkitStorageInfo و navigator.webkitTemporaryStorage

مرورگرها از لحاظ تاریخی از این نوع درون نگری از طریق رابط های پیشوندی پشتیبانی می کنند، مانند window.webkitStorageInfo بسیار قدیمی (و منسوخ شده) و navigator.webkitTemporaryStorage نه چندان قدیمی اما هنوز غیر استاندارد. در حالی که این رابط ها اطلاعات مفیدی را ارائه می دهند، اما آینده ای به عنوان استانداردهای وب ندارند.

اینجاست که WHATWG Storage Standard وارد تصویر می شود.

آینده: navigator.storage

به عنوان بخشی از کار در حال انجام بر روی Storage Living Standard ، چند API مفید به رابط StorageManager راه یافته اند که به عنوان navigator.storage در معرض مرورگرها قرار می گیرد. مانند بسیاری دیگر از APIهای وب جدیدتر، navigator.storage فقط در منابع امن (ارائه شده از طریق HTTPS یا میزبان محلی) در دسترس است.

سال گذشته، ما متد navigator.storage.persist() را معرفی کردیم که به برنامه وب شما اجازه می‌دهد تا درخواست کند که فضای ذخیره‌سازی آن از پاکسازی خودکار معاف شود.

اکنون با متد navigator.storage.estimate() که به عنوان جایگزینی مدرن برای navigator.webkitTemporaryStorage.queryUsageAndQuota() می‌پیوندد. estimate() اطلاعات مشابهی را برمی گرداند، اما یک رابط مبتنی بر وعده را نشان می دهد که با دیگر API های ناهمزمان مدرن همخوانی دارد. وعده ای که 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 منعکس کننده تعداد بایت هایی است که یک مبدأ معین به طور موثر برای داده های همان منبع استفاده می کند، که به نوبه خود می تواند تحت تأثیر تکنیک های فشرده سازی داخلی، بلوک های تخصیص اندازه ثابت که ممکن است فضای بلااستفاده را شامل شود، و وجود رکوردهای "سنگ قبر" که ممکن است باشد. به طور موقت پس از حذف ایجاد شد. برای جلوگیری از نشت اطلاعات اندازه دقیق، منابع غیرشفاف و متقاطع ذخیره شده به صورت محلی ممکن است بایت‌های padding اضافی را به مقدار usage کلی کمک کنند.
  • quota نشان دهنده مقدار فضایی است که در حال حاضر برای یک مبدا رزرو شده است. این مقدار به برخی از عوامل ثابت مانند اندازه کلی فضای ذخیره‌سازی، اما به تعدادی از عوامل بالقوه فرار، از جمله مقدار فضای ذخیره‌سازی که در حال حاضر استفاده نشده است، بستگی دارد. بنابراین، همانطور که سایر برنامه‌های روی یک دستگاه داده‌ها را می‌نویسند یا حذف می‌کنند، مقدار فضایی که مرورگر مایل است به مبدا برنامه وب شما اختصاص دهد احتمالاً تغییر خواهد کرد.

حال: تشخیص ویژگی و بازگشت

estimate() به طور پیش‌فرض با شروع Chrome 61 فعال است. فایرفاکس در حال آزمایش با 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});
}