تقدير مساحة التخزين المتاحة

النص المختصر

يعرض الآن الإصدار 61 من Chrome، بالإضافة إلى المزيد من المتصفحات، تقديرًا لمساحة التخزين التي يستخدمها تطبيق الويب والمساحة المتوفّرة من خلال:

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

تطبيقات الويب الحديثة وتخزين البيانات

عند التفكير في احتياجات التخزين لتطبيق ويب حديث، من المفيد تقسيم ما يتم تخزينه إلى فئتين: البيانات الأساسية اللازمة لتحميل تطبيق الويب والبيانات اللازمة للتفاعل الهادف مع المستخدم بعد تحميل التطبيق.

النوع الأول من البيانات، وهو ما يلزم لتحميل تطبيق الويب، يتألف من HTML و JavaScript وCSS، وربما بعض الصور. توفّر خدمات العمال، بالإضافة إلى Cache Storage API، البنية الأساسية اللازمة لحفظ هذه الموارد الأساسية ثم استخدامها لاحقًا لتحميل تطبيق الويب بسرعة، ويُفضّل تخطّي الشبكة بالكامل. (إنّ الأدوات التي يتم دمجها مع عملية إنشاء تطبيق الويب، مثل مكتبات Workbox الجديدة أو مكتبات sw-precache القديمة، يمكنها أتمتة عملية تخزين هذا النوع من البيانات وتعديلها واستخدامها بالكامل).

ماذا عن النوع الآخر من البيانات؟ هذه هي الموارد التي لا يلزم استخدامها لتحميل تطبيق الويب، ولكن قد تلعب دورًا مهمًا في تجربته الإجمالية. على سبيل المثال، إذا كنت تكتب تطبيق ويب لتعديل الصور، قد تحتاج إلى حفظ نسخة واحدة أو أكثر من صورة على الجهاز، ما يسمح للمستخدمين بالتبديل بين المراجعات وإلغاء عملهم. أو إذا كنت تُطوّر تجربة تشغيل وسائط بلا إنترنت، سيكون حفظ ملفات الصوت أو الفيديو على الجهاز ميزة مهمة. إنّ كل تطبيق ويب يمكن تخصيصه يحتاج في النهاية إلى حفظ نوع من معلومات الحالة. كيف يمكنك معرفة مقدار المساحة المتاحة لهذا النوع من مساحة التخزين أثناء التشغيل، وما الذي يحدث عند نفاد المساحة؟

الفترة السابقة: window.webkitStorageInfo وnavigator.webkitTemporaryStorage

كانت المتصفّحات توفّر هذا النوع من الاستكشاف الذاتي من خلال واجهة مسبوقة ببادئة، مثل واجهة window.webkitStorageInfo القديمة جدًا (والتي تم إيقافها نهائيًا) وواجهة navigator.webkitTemporaryStorage التي ليست قديمة جدًا، ولكنها لا تزال غير قياسية. على الرغم من أنّ هذه الواجهات قدّمت معلومات مفيدة، إلا أنّها لا تملك مستقبلًا كمعايير ويب.

وهنا يأتي دور معيار التخزين في WHATWG.

المستقبل: navigator.storage

في إطار العمل الجاري على Storage Living Standard، تم تضمين واجهتَي برمجة تطبيقات مفيتَين في واجهة StorageManager ، والتي يتم عرضها للمتصفّحات باسم navigator.storage. مثل العديد من واجهات برمجة تطبيقات الويب الأحدث الأخرى، لا تتوفّر navigator.storage إلا على مصادر آمنة (يتم عرضها من خلال HTTPS أو 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() تلقائيًا بدءًا من الإصدار 61 من Chrome. يختبر 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});
}