什么是 IndexDB
随着浏览器的功能逐渐增强,我们不可避免的需要在前端处理越来越多的数据,除了数据,我们甚至可能需要对 cache 作出更加丰富的操作。
那么问题来了,用什么工具更加合适呢?
cookie 是我们常见数据持久化方案,但是他的大小仅仅只有 4k,并且随着 cookie 的增大,你的请求携带的cookie 也随之增加,这显然是不划算的。
localstorage 是一个不错的方案,他的大小也是勉强够用的,约 2.5M 随着各个浏览器大小的不同而发生改变,比如 chrome1 他的大小就有 10M
当然咯有一些成熟的库对 localstorage 作出了一定程度上的封装来减少存取的难度,但是实际上,它在某些痛点上并不能很好的解决这些问题。(这会在后文指出)
所以 IndexDB 应运而生,用于处理这些复杂而麻烦的任务。
IndexDB 顾名思义,是一个 db。
各位前端的小伙伴相比都是用 node 的,对于 node 我们最喜欢也最常用的是 mongodb。
IndexDB 和 mongo 类似 是一个 nosql 数据库,并且非常像 redis,是一个 键值数据库,所以这货所存储的聚合不一定非要是领域对象,任何数据结构都可以,比如list、set、hash
等数据结构,而且支持某些高级的集合操作,比如求 交集/并集/差集 (当然用起来不是一般的麻烦,我觉得 LINQ 才是最好的数据处理方式)
为什么 IndexDB
那么就需要讲讲为什么要用 IndexDB 了,任何技术都有其适用环境,那么 IndexDB 的优点是什么呢?
- 异步
- key-value 形式保存数据,几乎所有的 js 类型都能被储存在内(数组,对象等)
- 支持事务
- 储存空间极大,最少 250MB,最大可以达到硬盘容量的 20%(域策略限制) * 50%(浏览器策略限制) = 10%
- 支持二进制储存(blob,buffer)
显而易见的这货是一个 数据库 。
那么应用的场景就很明确了,比如你需要前端数据库的时候自然而然的就会考虑用上他了。
比如,你作为一个浏览器端的工具,需要离线使用,并且你是一个 博客编辑器,那就很有意思了,假设断网了,你的 post 岂不是不能用?当然不是的,结合 pwa + IndexDB,他可以在脱机情况下正常使用,直至网络恢复,在重新使用 IndexDB 内部的数据同步到服务器。
这是一个合理的应用场景,因为 localstorage 不能很好的支持图片缓存,而 IndexDB 却能很好的提供支持。
更有意思的是,你离线的时候,由于博文的内容已经被下载下来,那么自然而然的,脱机情况下你可以访问任何已经被缓存的数据,甚至像有网络的时候一样去用它。
兼容性
怎么使用?
IndexDb 原生的概念有点复杂,并且包含了很多数据库相关的知识,如果有数据的经验,你会更好的掌握他的使用方法。
不过由于IndexDB 的 API 过于接近底层,事实上远远不如 sql 来的直观好用。
IndexDB 的对象
- 数据库对象
- 对象仓库
- 索引
- 事务
- 操作请求
- 指针
- 主键集合
对于 IndexDB我这里只是简单的讲述一下如何建立一个数据库并且链接,如何增删改查,更加细节的内容则不多赘述,建议前往 MDN 学习 / 或者看 阮老师的 相关博客2
这里简单的列一下详细内容建议参考 wangDoc.com3
更好的解决方案
原生的 IndexDB 讲句实话,非常的不直观,也不符合正常的使用逻辑。
那么有更好的解决方案么?
当然有的,那就是 dexieJs !
这是一套相对简单的 ORM 框架(个人认为),他提供了一套更加符合直觉和用户常用习惯的 api 辅助使用。
那么如何使用捏,这边举一个例子:
就比如上面这些 db 操作常见的增删改查都出现了,基本可以覆盖绝大部分使用情况了。
这里 有新手教学,以及更加详细的 API
注意事项
这里值得注意的是,IndexDB 也有着和 后端数据库一样的问题,就是批量修改远大于多次修改。
反应在 dexie 上就是:
10000 个 role 的创建需要约 18秒,而 bulkAdd 或者 bulkPut 只需要约 70 - 120
毫秒不到。如果添加了主键索引则速度可以更快。
当然你插入的时候可以不用 await 来显著的提升性能,卡浏览器的事儿能叫提升性能么,什么叫做卡死标签页【战术后仰】
当然咯,受限于实现,如果按照后端的那种方式去用的话,相比较后端成熟的 MySQL/MariaDB/PostgreSQL/Oracle
等数据库简直慢的如牛爬,但是对于前端这种,对于查询时间相对并不是太过敏感的使用环境,其查询速度的缺点已经被其巨大的优势所掩盖,当然事实上我们还有一个更加强大的工具 —— websql(可惜这货只有chrome 可怜巴巴的支持。)