Storage API简介和存储限制与逐出策略

简介

对于现代浏览器来讲,为了提高效率和处理更加复杂的客户端操做,一般都须要将数据存储在客户端,也就是本地磁盘上。那么这个存储有没有什么限制?若是数据存满了以后,如何进行数据的淘汰和置换?web

一块儿来看看吧。算法

经常使用的客户端存储方式

客户的存储方式都有哪些呢?api

咱们看一下比较经常使用的几种方式:浏览器

  • IndexedDB
  • asm.js caching
  • Cache API
  • Cookies
  • web storage

固然还有其余的客户端存储类型,好比AppCache(已经被废弃),File System API(非标准的API)等。缓存

data storage的类型

一般来讲,data storage有两种方式,一种是永久性的,这种状况下一般数据会存储比较长的时间,除非用户选择清除(好比清除浏览器缓存),不然数据将会永久保存。fetch

一种是临时存储,这种状况下,数据会存储有限的时间。数据存储的容量是有限的,在有限的数据容量空间,咱们须要一些特定的数据逐出算法来保证有效的数据不会被覆盖。url

逐出策略

在使用临时存储模式时,咱们一般使用的逐出策略是LRU。spa

当到达存储的限额的时候,将会查找全部当前未使用的origin,而后根据最后访问时间对他们进行排序。而后删除最近最少使用的origin信息。code

Storage API

为了统一和规范这些客户端的操做API,因而引入了Storage API,经过Storage API咱们能够查看可用存储空间大小,已使用的空间大小,甚至能够控制在用户数据清除的时候是否须要提醒用户。对象

注意Storage API只适用于HTTPS的状况,而且只是部分浏览器支持。

为了对不一样源的数据进行管理,引入了storage units(也叫作box)的概念,对于每个源来讲,都有一个storage units(Box)。

不一样的storage units里面能够存储不一样类型的数据。

上图中Origin 1中既有Web Storage,也有IndexedDB的存储,由于并无达到Storage的最大值,因此还留有必定的空余空间。

Origin 2中尚未开始存储任何数据,因此都是空的。

Origin 3中被indexedDB存满了,没有任何空余空间。

为了方便管理box有两种模式,一种叫best-effort,一种叫persistent。

best-effort模式是指浏览器会尽最大努力去保留数据,可是当存储空间用完的时候,浏览器并不会提醒用户可能对存储空间的清理操做。

persistent模式将会尽量长时间的保存用户的数据,若是同时有best-effort和persistent模式的话,当存储空间不足的时候,将会首先清除best-effort box。若是必定要清除persistent box,将会通知相应的用户。

Storage API指的就是StorageManager,它有三个很是重要的方法estimate,persist和persisted,咱们看下他们的浏览器兼容性:

基本上,现代浏览器都支持StorageManager和它的三个方法。

下面咱们分别来看一下他们的使用。

StorageManager是一个接口,用来管理存储的权限和评估可用的空间。咱们能够经过navigator.storage 或者WorkerNavigator.storage 来获取到StorageManager。

咱们看一下StorageManger的定义:

interface StorageManager {
    estimate(): Promise<StorageEstimate>;
    persist(): Promise<boolean>;
    persisted(): Promise<boolean>;
}

estimate

estimate方法返回一个Promise,Promise中包含一个StorageEstimate对象,表示空间的使用状况和限额。

navigator.storage.estimate().then(estimate => {
  // estimate.quota is the estimated quota
  // estimate.usage is the estimated number of bytes used
});

咱们使用estimate来查看是否有住够的空间进行应用数据的存储:

function retrieveNextChunk(nextChunkInfo) {
  return navigator.storage.estimate().then(info => {
    if (info.quota - info.usage > nextChunkInfo.size) {
      return fetch(nextChunkInfo.url);
    } else {
      throw new Error("insufficient space to store next chunk");
    }
  }).then( /* … */ );
}

上面是一个estimate的使用。

persist

persist方法返回一个Promise,true表示user agent已被受权,而且box mode= persistent模式。

咱们看一下persist 的使用:

if (navigator.storage && navigator.storage.persist)
  navigator.storage.persist().then(function(persistent) {
    if (persistent)
      console.log("Storage will not be cleared except by explicit user action");
    else
      console.log("Storage may be cleared by the UA under storage pressure.");
  });

persisted

persisted方法返回一个Promise,true表示box mode= persistent模式。

咱们看一个persisted的例子:

if (navigator.storage && navigator.storage.persist) 
  navigator.storage.persisted().then(function(persistent) {
    if (persistent)
      console.log("Storage will not be cleared except by explicit user action");
    else
      console.log("Storage may be cleared by the UA under storage pressure.");
  });

综合使用

以前讲到了,若是是persistent模式,数据的清理须要通知用户,下面咱们看一下这个判断该怎么写:

Promise.all([
  navigator.storage.persisted(),
  navigator.permissions.query({name: "persistent-storage"})
]).then(([persisted, permission]) => {
  if (!persisted && permission.status == "granted") {
    navigator.storage.persist().then( /* … */ );
  } else if (!persisted && permission.status == "prompt") {
    showPersistentStorageExplanation();
  }
});

上面的例子,咱们还使用到了Permissions API。经过Permissions API,咱们来判断用户所拥有的权限。

Permissions API仍是一个比较新的API,只有在Chrome 44和Firefox 43以后才支持。

咱们能够经过navigator.permissions来获取到Permissions API。

能够经过Permissions.query()来判断是否具备相应的权限。

Permissions.query将会返回一个PermissionStatus对象,这个对象表明了三个状态:granted,prompt和denied。

咱们看一个判断权限的应用:

function handlePermission() {
  navigator.permissions.query({name:'geolocation'}).then(function(result) {
    if (result.state == 'granted') {
      report(result.state);
      geoBtn.style.display = 'none';
    } else if (result.state == 'prompt') {
      report(result.state);
      geoBtn.style.display = 'none';
      navigator.geolocation.getCurrentPosition(revealPosition,positionDenied,geoSettings);
    } else if (result.state == 'denied') {
      report(result.state);
      geoBtn.style.display = 'inline';
    }
    result.onchange = function() {
      report(result.state);
    }
  });
}

function report(state) {
  console.log('Permission ' + state);
}

handlePermission();

除了Query,咱们还可使用revoke来取消受权。

function revokePermission() {
  navigator.permissions.revoke({name:'geolocation'}).then(function(result) {
    report(result.state);
  });

总结

Storage API是为了统一客户端存储标准所制定的API。还在不断的完善之中。感兴趣的朋友能够多多关注它的进展。

本文做者:flydean程序那些事

本文连接:http://www.flydean.com/storage-api-limit/

本文来源:flydean的博客

欢迎关注个人公众号:「程序那些事」最通俗的解读,最深入的干货,最简洁的教程,众多你不知道的小技巧等你来发现!

相关文章
相关标签/搜索