Estimar o espaço de armazenamento disponível

Texto longo, leia o resumo

O Chrome 61, com mais navegadores no futuro, agora mostra uma estimativa de quanto armazenamento usado por um app da Web e a quantidade disponível via:

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

Apps da Web e armazenamento de dados modernos

Quando você pensa nas necessidades de armazenamento de um aplicativo da Web moderno, é útil dividir o que está sendo armazenado em duas categorias: os principais dados necessários para carregar o aplicativo da Web e os dados necessários para uma interação significativa do usuário do aplicativo carregado.

O primeiro tipo de dado, que é necessário para carregar seu aplicativo da web, consiste em HTML, JavaScript, CSS e talvez algumas imagens. Os service workers, além dos a API Cache Storage, fornecer a infraestrutura necessária para salvar esses recursos e depois usar mais tarde para carregar rapidamente seu aplicativo da web, de preferência ignorando completamente a rede. (Ferramentas que se integram ao processo de compilação de aplicativos da web, como as novas Workbox ou as mais antigas. sw-precache, pode automatizar totalmente o processo de armazenamento, atualização e uso desse tipo de data.)

Mas e quanto ao outro tipo de dados? Esses são recursos que não são necessários para carregam seu app da Web, mas isso pode desempenhar um papel crucial na segurança do usuário. Se você estiver escrevendo um app da Web de edição de imagens, por exemplo, é possível quiser salvar uma ou mais cópias locais de uma imagem, permitindo que os usuários alternem entre revisões e desfazer o trabalho. Ou, se estiver desenvolvendo uma experiência de mídia off-line, experiência de reprodução, salvar localmente arquivos de áudio ou vídeo seria essencial . Todo aplicativo da web que pode ser personalizado acaba precisando economizar um pouco um tipo de informação de estado. Como saber quanto espaço há disponível para esse tipo de armazenamento em tempo de execução? e o que acontece quando você fica sem espaço?

No passado: window.webkitStorageInfo e navigator.webkitTemporaryStorage

Historicamente, os navegadores suportam esse tipo de introspecção por meio de do Google, como as interfaces muito antigas (e descontinuadas) window.webkitStorageInfo, e não tão antiga, mas ainda não padrão navigator.webkitTemporaryStorage Embora essas interfaces forneçam informações úteis, elas não têm futuro enquanto padrões da Web.

É aí que entra o Padrão de armazenamento WhatWG entra na imagem.

O futuro: navigator.storage

Como parte do trabalho contínuo no Storage Living Standard (em inglês), algumas APIs úteis foram para a StorageManager que é exposta aos navegadores como navigator.storage Como muitas outras APIs da Web mais recentes, a navigator.storage só está disponível em APIs seguras (veiculado por HTTPS ou localhost).

No ano passado, apresentamos a navigator.storage.persist() , que permite ao seu aplicativo da Web solicitar que seu armazenamento seja isentos da limpeza automática.

Agora ela é unida pelo método navigator.storage.estimate(), que serve como substituto moderno para navigator.webkitTemporaryStorage.queryUsageAndQuota(). estimate() retorna informações semelhantes, mas expõe uma baseada em promessa, que está de acordo com outras APIs assíncronas modernas. A promessa de que estimate() retorna se resolve com um objeto que contém duas propriedades: usage, que representa o número de bytes usados no momento, e quota, que representa o máximo de bytes que podem ser armazenados pelo servidor origin. Como tudo relacionado ao armazenamento, a cota é aplicada a todo o origin.)

Se um aplicativo da Web tentar armazenar, por exemplo, o IndexedDB ou o API Cache Storage: dados grandes o suficiente para trazer uma determinada origem a cota disponível, a solicitação falhará QuotaExceededError exceção.

Estimativas de armazenamento em ação

A forma como você usa estimate() depende do tipo de dados que o app precisa loja on-line. Por exemplo, é possível atualizar um controle na interface para que os usuários saber quanto espaço está sendo usado após a conclusão de cada operação de armazenamento. O ideal é fornecer uma interface que permita aos usuários limpar manualmente os dados que não é mais necessária. Você pode escrever o código nas linhas de:

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

Qual é a precisão da estimativa?

É difícil deixar passar o fato de que os dados que você recebe da função são apenas uma estimativa do espaço usado por uma origem. Está bem ali na função nome! Os valores usage e quota não precisam ser estáveis. Portanto, é recomendável considerar o seguinte:

  • usage reflete quantos bytes uma determinada origem está usando efetivamente para mesma origem que, por sua vez, podem ser afetados por técnicas de compactação interna, blocos de alocação de tamanho fixo que podem incluir espaço não utilizado de "tombstone" registros que podem ser criadas temporariamente após uma exclusão. Para evitar o vazamento de informações de tamanho exato, origem cruzada, recursos opacos salvos localmente podem contribuir com bytes de padding extras para o usage geral .
  • quota reflete a quantidade de espaço atualmente reservado para uma origem. A depende de alguns fatores constantes, como o tamanho geral do armazenamento, mas também número de fatores potencialmente voláteis, incluindo a quantidade de espaço de armazenamento que não está sendo usado no momento. Assim como outros aplicativos em um dispositivo gravam ou excluem a quantidade de espaço que o navegador está disposto a dedicar ao seu site a origem do app provavelmente mudará.

Presente: detecção de recursos e substitutos

estimate() é ativado por padrão a partir do Chrome 61. O Firefox é testando o navigator.storage, mas, desde agosto de 2017, ainda não houve são ativados por padrão. Você precisa ativar a preferência dom.storageManager.enabled; para testá-lo.

Ao trabalhar com uma funcionalidade que ainda não tem suporte em todos os navegadores, a detecção de recursos é imprescindível. É possível combinar a detecção de recursos um wrapper baseado em promessa sobre o navigator.webkitTemporaryStorage mais antigo métodos para fornecer uma interface consistente ao longo das linhas de:

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