Progressive Web App 用户端储存简介 (13)

什麽是用户端储存 (Client-side storage)

对一个 App 来说,为了达到某些目的,将相关资料存在用户端是相对方便的,举例来说

  • 个人偏好设定,像是常用功能、颜色主题、字体大小
  • 将前一次操作快取,像是纪录购物车资料或是线上编辑器在断线时先暂时将资料保存
  • 不常改变的资料或静态资源快取
  • 离线操作所需要的档案

通常用户端的储存和服务器端的储存会是一起搭配使用的,举例来说当我们使用影音串流功能时,会从服务器端下载相关资料到用户端使用,在过程中 App 也能够将资料快取起来以便下次使用。

不过在实务上,浏览器用户端的储存目前有各式解决方案,也都有着各自的限制存在,如果是有大小限制的储存,就必须注意定时和服务器端同步去避免资料遗失。

常见用户端储存机制介绍

目前常见的用户端储存机制如下:

  • Cookies: 每次发 Request 都会一起送出,所以要大小控制要注意
  • Web Storage API
    • SessionStorage: 同步阻塞 (synchronous),上限 5MB,仅存在於 Tab 当次操作,无法被 web workers 或 service workers 使用
    • LocalStorage: 同步阻塞 (synchronous),上限 5MB,无法被 web workers 或 service workers 使用
  • Cache API: 非同步,较适合跟网路请求相关的静态资源快取
  • IndexedDB API: 非同步,适合储存程序逻辑相关资料,使用上相对复杂,较推荐使用像是 idb 这类相关套件操作
  • WebSQL: 不建议使用

用户端储存限制

一般来说储存空间的上限如下:

  • Chrome 总共最多可以用到 80% 的硬碟,每个网域最高是 60%
  • IE 系列 10 以後最多 250MB
  • Firefox 硬碟空间的 50%
  • Safari 1GB

在 Chrome、Firefox、Edge 等浏览器中可以使用以下的程序码去估计剩余空间:

https://caniuse.com/mdn-api_storagemanager

if (navigator.storage && navigator.storage.estimate) {
  const quota = await navigator.storage.estimate();
  // quota.usage -> 用了多少 bytes
  // quota.quota -> 还剩多少 bytes 可使用
  const percentageUsed = (quota.usage / quota.quota) * 100;
  console.log(`${percentageUsed}% 已使用`);
  const remaining = quota.quota - quota.usage;
  console.log(`还可以写入 ${remaining} bytes`);
}

QuotaExceededError 错误处理

  • IndexedDB
const transaction = idb.transaction(["entries"], "readwrite");
transaction.onabort = function (event) {
  const error = event.target.error; // DOMException
  if (error.name == "QuotaExceededError") {
    // 错误处理
  }
};
  • Cache API
try {
  const cache = await caches.open("my-cache");
  await cache.add(new Request("/test.jpg"));
} catch (err) {
  if (error.name === "QuotaExceededError") {
    // 错误处理
  }
}

储存淘汰机制 (eviction)

资料在储存上会分成两种类别

  • Best Effort: 当浏览器空间不足,会开始执行淘汰机制
    • Chromium: 从最少使用的开始,会自动清除资料且不会通知用户
    • Firefox: 从最少使用的开始,会自动清除资料且不会通知用户
    • Internet Explorer 10+ 不会清除,但会停止写入
  • Persistent: 不会被自动清除

LRU policy

当硬碟空间即将用完时,浏览器会依据 LRU policy (least recently used) 的规则透过去清除快取档案。

  1. 目前没有使用的网页 (tabs/apps)
  2. 比对最後存取的时间

Persistent Storage

为了避免资料被储存淘汰机制处理掉,我们能够通过程序码去确认、启用 Persistent Storage。

// 确认目前储存空间是否套用 Persistent
if (navigator.storage && navigator.storage.persist) {
  const isPersisted = await navigator.storage.persisted();
  console.log(`Persisted storage granted: ${isPersisted}`);
}

// 针对这个站台启用 Persistent Storage
if (navigator.storage && navigator.storage.persist) {
  const isPersisted = await navigator.storage.persist();
  console.log(`Persisted storage granted: ${isPersisted}`);
}

启用过後底下的储存皆会受到保护,但要注意启用後目前尚没有透过程序停用的方式。

  • Cache API
  • Cookies
  • DOM Storage (Local Storage)
  • File System API
  • IndexedDB
  • Service workers
  • App Cache (deprecated)
  • WebSQL (deprecated)

<<:  【Day 11】C 语言的赋值运算子

>>:  [Day26] 猜数字小游戏

Unity与Photon的新手相遇旅途 | Day11-敌人攻击

今天的内容为该如何简单制作出一个自动攻击的敌人 ...

【Day15】数据展示元件 - Carousel

元件介绍 Carousel 是一个像旋转木马一样会轮流转的轮播元件。在一个内容空间有限的可视范围中进...

课堂笔记 - 深度学习 Deep Learning (17)

在向量中求各个方向的梯度下降: Gradients and Directional Derivati...

<Day15>Ticks — 取得选择权(Options)逐笔成交资料

● 这章来示范如何取得选择权(Options)的ticks 回顾上一章,我们学会如何取得特定时段的期...

Day35 ( 电子元件 ) LED 显示温湿度 ( DHT11 )

LED 显示温湿度 ( DHT11 ) 教学原文参考:LED 显示温湿度 ( DHT11 ) 这篇文...