并非所有存储空间都是一样的:引入 Storage 存储分区

存储标准定义了用于永久性存储和配额估算的 API,以及平台存储架构。我们将推出一项 API,以便在内存压力较大时更可预测地驱逐永久存储空间。该 API 从 Chromium 122 开始提供。

存储标准解决了哪些问题?

传统上,当用户设备上的存储空间用尽时,使用 IndexedDB 或 localStorage 等 API 存储的数据会丢失,而用户无法干预。一种使存储空间持久化的方法是调用 StorageManager 接口的 persist() 方法。它会同时向最终用户请求权限,并在获得授权后将存储空间更改为永久存储空间:

const persisted = await navigator.storage.persist();
if (persisted) {
  /* Storage will not be cleared except by explicit user action. */
}

这种请求将存储空间持久化的方法是“全部或全无”。无法表达更精细的持久化需求。它们都属于一个存储分区。

Storage Buckets API

Storage Buckets API 的核心理念是授予网站创建多个存储分区的权限,其中浏览器可以选择独立于其他存储分区来删除每个存储分区。这样,开发者就可以指定驱逐优先级,以确保不会删除最有价值的数据。

应用场景示例

为了说明存储分区在哪些方面会派上用场,我们假设有一个电子邮件应用。如果应用丢失了仅存在于客户端上的用户未发送的草稿,那将是不可原谅的。相比之下,如果这些数据存储在服务器上,当用户的浏览器存储压力过大时,他们可能不会介意从客户端中移除一些最早的收件箱电子邮件。

电子邮件应用界面
电子邮件应用,其中收件箱和草稿有单独的存储分区。(仅作说明之用,不一定反映 Gmail 的运作方式。)

使用 Storage Buckets API

创建新的存储分区

您可以使用 StorageBucketManager 接口上的 open() 方法创建新的存储分区。

// Create a storage bucket for emails that are synchronized with the
// server.
const inboxBucket = await navigator.storageBuckets.open('inbox');

创建新的永久性存储分区

为确保存储分区持久保留,您可以将 durabilitypersisted 选项参数传递给 open() 方法:

  • persisted 用于确定是否应保留存储分区。允许的值为 false(默认)或 true
  • durability 会向浏览器提供提示,帮助浏览器在写入性能和降低断电时数据丢失风险之间进行权衡。允许的值为 'relaxed'(默认)或 'strict'

    • 'strict' 分桶会尽量降低在断电时数据丢失的风险。但这可能会降低性能,也就是说,写入操作可能需要更长时间才能完成,可能会影响整体系统性能,可能会增加电池耗电量,并且可能会更快地耗损存储设备。
    • 当发生断电时,'relaxed' 存储分区可能会“忘记”在过去几秒内完成的写入。反过来,将数据写入这些存储分区可能会具有更好的性能特性,并且可以延长电池充电续航时间,还可能会延长存储设备的使用寿命。此外,与 'strict' 存储分区相比,停电导致数据损坏的几率不会更高。
// Create a storage bucket for email drafts that only exist on the client.
const draftsBucket = await navigator.storageBuckets.open('drafts', {
  durability: 'strict', // Or `'relaxed'`.
  persisted: true, // Or `false`.
});

从存储分区访问存储空间 API

每个存储分区都与存储 API 相关联,例如 IndexedDBCache 接口或 File 接口。这些存储空间 API 的运作方式与往常一样,只不过入口点来自 StorageBucket 接口,例如 StorageBucket.indexedDB

const inboxDb = await new Promise(resolve => {
  const request = inboxBucket.indexedDB.open('messages');
  request.onupgradeneeded = () => { /* migration code */ };
  request.onsuccess = () => resolve(request.result);
  request.onerror = () => reject(request.error);
});

在开发者工具中调试存储分区

Application(应用)> Storage(存储)部分中,检查专用树中的存储分区。

在“存储”部分启用存储分区树之前和之后。

实用资源