Memperkirakan Ruang Penyimpanan yang Tersedia

tl;dr

Chrome 61, dengan lebih banyak browser yang akan mengikuti, kini menampilkan estimasi jumlah penyimpanan yang digunakan aplikasi web dan jumlah yang tersedia melalui:

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

Aplikasi web modern dan penyimpanan data

Saat Anda memikirkan kebutuhan penyimpanan aplikasi web modern, akan lebih mudah jika apa yang disimpan dibagi menjadi dua kategori: data inti yang diperlukan untuk memuat aplikasi web, dan data yang diperlukan untuk interaksi pengguna yang bermakna setelah aplikasi dimuat.

Jenis data pertama, yang diperlukan untuk memuat aplikasi web Anda, terdiri dari HTML, JavaScript, CSS, dan mungkin beberapa gambar. Service worker, bersama dengan Cache Storage API, menyediakan infrastruktur yang diperlukan untuk menyimpan resource inti tersebut, lalu menggunakannya nanti untuk memuat aplikasi web Anda dengan cepat, idealnya dengan mengabaikan jaringan sepenuhnya. (Alat yang terintegrasi dengan proses build aplikasi web Anda, seperti library Workbox baru atau sw-precache lama, dapat sepenuhnya mengotomatiskan proses penyimpanan, pembaruan, dan penggunaan jenis data ini.)

Namun, bagaimana dengan jenis data lainnya? Ini adalah resource yang tidak diperlukan untuk memuat aplikasi web, tetapi mungkin berperan penting dalam pengalaman pengguna keseluruhan. Misalnya, jika Anda menulis aplikasi web pengeditan gambar, Anda mungkin ingin menyimpan satu atau beberapa salinan lokal gambar, yang memungkinkan pengguna beralih antara revisi dan mengurungkan pekerjaan mereka. Atau, jika Anda mengembangkan pengalaman pemutaran media offline, menyimpan file audio atau video secara lokal akan menjadi fitur penting. Setiap aplikasi web yang dapat dipersonalisasi pada akhirnya perlu menyimpan beberapa informasi status. Bagaimana cara mengetahui jumlah ruang yang tersedia untuk jenis penyimpanan runtime ini, dan apa yang terjadi jika ruang penyimpanan habis?

Masa lalu: window.webkitStorageInfo dan navigator.webkitTemporaryStorage

Browser secara historis telah mendukung jenis introspeksi ini melalui antarmuka dengan awalan, seperti window.webkitStorageInfo yang sangat lama (dan tidak digunakan lagi), dan navigator.webkitTemporaryStorage yang tidak terlalu lama, tetapi masih non-standar. Meskipun antarmuka ini memberikan informasi yang berguna, antarmuka ini tidak memiliki masa depan sebagai standar web.

Di sinilah Standar Penyimpanan WHATWG memasuki gambar.

Masa mendatang: navigator.storage

Sebagai bagian dari pekerjaan yang sedang berlangsung pada Storage Living Standard, beberapa API yang berguna telah dibuat untuk antarmuka StorageManager, yang diekspos ke browser sebagai navigator.storage. Seperti banyak API web baru lainnya, navigator.storage hanya tersedia di origin yang aman (ditayangkan melalui HTTPS, atau localhost).

Tahun lalu, kami memperkenalkan metode navigator.storage.persist(), yang memungkinkan aplikasi web Anda meminta penyimpanannya dikecualikan dari pembersihan otomatis.

Sekarang, metode ini digabungkan dengan metode navigator.storage.estimate(), yang berfungsi sebagai pengganti navigator.webkitTemporaryStorage.queryUsageAndQuota() yang modern. estimate() menampilkan informasi serupa, tetapi mengekspos antarmuka berbasis promise, yang sesuai dengan API asinkron modern lainnya. Promise yang ditampilkan oleh estimate() di-resolve dengan objek yang berisi dua properti: usage, yang mewakili jumlah byte yang saat ini digunakan, dan quota, yang mewakili byte maksimum yang dapat disimpan oleh asal saat ini. (Seperti semua hal lain yang terkait dengan penyimpanan, kuota diterapkan di seluruh origin.)

Jika aplikasi web mencoba menyimpan—menggunakan, misalnya, IndexedDB atau Cache Storage API—data yang cukup besar untuk membawa origin tertentu melebihi kuota yang tersedia, permintaan akan gagal dengan pengecualian QuotaExceededError.

Cara kerja estimasi penyimpanan

Cara Anda menggunakan estimate() bergantung pada jenis data yang perlu disimpan aplikasi Anda. Misalnya, Anda dapat memperbarui kontrol di antarmuka untuk memberi tahu pengguna jumlah ruang yang digunakan setelah setiap operasi penyimpanan selesai. Idealnya, Anda akan menyediakan antarmuka yang memungkinkan pengguna membersihkan data secara manual yang tidak lagi diperlukan. Anda dapat menulis kode seperti:

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

Seberapa akurat estimasinya?

Sulit untuk mengabaikan fakta bahwa data yang Anda dapatkan kembali dari fungsi ini hanyalah estimasi ruang yang digunakan asal. Namanya ada di nama fungsi. Nilai usage maupun quota tidak dimaksudkan untuk stabil, jadi sebaiknya pertimbangkan hal berikut:

  • usage mencerminkan jumlah byte yang digunakan origin tertentu secara efektif untuk data origin yang sama, yang pada akhirnya dapat terpengaruh oleh teknik kompresi internal, blok alokasi ukuran tetap yang mungkin mencakup ruang yang tidak digunakan, dan keberadaan data"tombstone" yang mungkin dibuat untuk sementara setelah penghapusan. Untuk mencegah kebocoran informasi ukuran yang tepat, resource buram lintas-asal yang disimpan secara lokal dapat berkontribusi pada byte padding tambahan ke nilai usage keseluruhan.
  • quota mencerminkan jumlah ruang yang saat ini dipesan untuk origin. Nilai ini bergantung pada beberapa faktor konstan seperti ukuran penyimpanan secara keseluruhan, tetapi juga sejumlah faktor yang berpotensi tidak stabil, termasuk jumlah ruang penyimpanan yang saat ini tidak digunakan. Jadi, saat aplikasi lain di perangkat menulis atau menghapus data, jumlah ruang yang bersedia dialokasikan browser untuk origin aplikasi web Anda kemungkinan akan berubah.

Saat ini: deteksi fitur dan penggantian

estimate() diaktifkan secara default mulai dari Chrome 61. Firefox sedang bereksperimen dengan navigator.storage, tetapi, mulai Agustus 2017, fitur ini tidak diaktifkan secara default. Anda harus mengaktifkan preferensi dom.storageManager.enabled untuk mengujinya.

Saat menggunakan fungsi yang belum didukung di semua browser, deteksi fitur adalah suatu keharusan. Anda dapat menggabungkan deteksi fitur bersama dengan wrapper berbasis promise di atas metode navigator.webkitTemporaryStorage lama untuk memberikan antarmuka yang konsisten dengan cara:

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