前言

在通才 3D 数字工厂项目中,由于场景文件(glb 资源文件)过大,并且每次加载页面时,glb 文件都会被重新加载,造成页面加载缓慢,最后通过保存生成 Blob 格式存储到 IndexedDB 中,增加文件缓存,减少资源重复加载。

为什么需要 IndexedDB

随着前端技术的发展和浏览器功能的不断增强,越来越多复杂的交互和业务需求需要前端来实现,其中一种常用的优化方式就是本地存储数据,减少从服务器获取数据,直接从本地获取数据也能提高页面渲染的速度。但先前的数据储存方案都不适合储存大量结构化数据,如 localStorage 容量通常在 10MB 以内(各家浏览器不同),储存的格式数据也有限,且不提供搜索功能,不能建立自定义的索引;因此需要一种新的解决方案,那就是 IndexedDB。

IndexedDB 是什么

IndexedDB 就是浏览器提供的本地数据库,它提供了一些底层 API,用于在客户端存储大量的结构化数据(也包括文件/二进制大型对象),并提供查找接口,还能建立索引。

IndexedDB 的特点

  • 键值对储存。IndexedDB 内部采用对象仓库存放数据。所有类型的数据都可以直接存入,包括 JavaScript 对象。对象仓库中,数据以”键值对”的形式保存,每一个数据记录都有对应的主键,主键是独一无二的,不能有重复,否则会抛出一个错误。
  • 异步操作。IndexedDB 操作时不会锁死浏览器,用户依然可以进行其他操作,这与 LocalStorage 形成对比,后者的操作是同步的。异步设计是为了防止大量数据的读写,拖慢网页的表现。
  • 支持事务。IndexedDB 支持事务(transaction),这意味着一系列操作步骤之中,只要有一步失败,整个事务就都取消,数据库回滚到事务发生之前的状态,不存在只改写一部分数据的情况。

数据库事务(transaction)是访问并可能操作各种数据项的一个数据库操作序列,这些操作要么全部执行,要么全部不执行,是一个不可分割的工作单位。事务由事务开始与事务结束之间执行的全部数据库操作组成。

  • 同源限制。IndexedDB 受到同源限制,每一个数据库对应创建它的域名。网页只能访问自身域名下的数据库,而不能访问跨域的数据库。
  • 储存空间大。IndexedDB 的储存空间比 localStorage 大得多,一般来说不少于 250MB,甚至没有上限(取决于硬盘大小)。
  • 支持二进制储存。IndexedDB 不仅可以储存字符串,还可以储存二进制数据(ArrayBuffer 对象和 Blob 对象)。

浏览器兼容性


判断当前浏览器是否支持 IndexedDB,可用如下代码:

window.indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDBif (!window.indexedDB) { alert('你的浏览器不支持IndexedDB')}

基础操作

打开/连接数据库

打开数据库使用indexedDB.open()方法

const request = window.indexedDB.open(name, version)
  • name:数据库名称。如果指定的数据库不存在,就会新建数据库。
  • version:指定数据库版本(整数)。如果省略,打开已有数据库时,默认为当前版本;新建数据库时,默认为 1。当你想要更改数据库格式(比如增加对象存储,非增加记录),必须指定更高版本。
  • 返回值:IDBOpenDBRequest 对象,这个对象通过三种事件 error、success、upgradeneeded,处理打开数据库的操作结果。
const request = window.indexedDB.open('myIndexedDB')// success 事件表示成功打开数据库request.onsuccess = (event) => { db = event.target.resultconsole.log('打开 IndexedDB 成功')}// error 事件表示打开数据库失败request.onerror = (event) => { console.log('打开 IndexedDB 失败')}// 如果指定的版本号,大于数据库的实际版本号,就会发生数据库升级事件 upgradeneeded request.onupgradeneeded = function (e) {