大家好,很高兴又见面了,我是"高级前端进阶",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发!
1.什么是 IndexedDBIndexedDB 是一个大型 NoSQL 存储系统,允许存储用户浏览器中的几乎所有内容。 除了常见的搜 search、get、put 操作之外,IndexedDB 还支持事务。
以下是 MDN 上 IndexedDB 和 NoSQL 的定义:
IndexedDB 是一个底层 API,用于客户端存储大量结构化数据(包括文件 / blob), 此 API 使用索引来实现对此数据的高性能搜索。 虽然 DOM 存储对于存储少量数据很有用,但对于存储大量结构化数据则不太有用,而 IndexedDB 提供了一个解决方案。NoSQL 数据库,又名 “not only SQL”,是非表格数据库,其数据存储方式与关系表不同。 根据数据模型,NoSQL 数据库有多种类型, 主要类型有:文档、键值、宽列和图表,其提供灵活的模式,并可以轻松扩展大量数据和高用户负载。每个 IndexedDB 数据库对于某个源(通常是站点域或子域)来说都是唯一的,这意味着其无法访问或被任何其他源访问。 数据存储限制通常相当大(如果存在的话),但不同的浏览器以不同的方式处理限制和数据清理。
可以通过下面方式判断浏览器是否支持 IndexedDB:
function indexedDBStuff () { // Check for IndexedDB support: if (!('indexedDB' in window)) { // Can't use IndexedDB console.log("This browser doesn't support IndexedDB"); return; } else { // Do IndexedDB stuff here: // ... }}// Run IndexedDB code:indexedDBStuff();2.什么是 idbidb 是一个很小的(~1.19kB)JavaScript 库,主要包括 IndexedDB API,但有一些小的改进,比如:可用性。idb 面向现代主流浏览器,包括: Chrome、Firefox、Safari 以及使用这些引擎的其他浏览器(例如 Edge),但是不包括 IE。
目前 idb 在 Github 通过 MIT 协议开源,有超过 5.8k 的 star、5970k 的项目使用量,NPM 周平均下载了 5,315k,是一个值得关注的前端优质开源项目。
如何使用 idb安装 idb首先需要通过 npm 安装:
npm install idb然后使用模块兼容的系统,如: webpack、Rollup 等:
import {openDB, deleteDB, wrap, unwrap} from 'idb';async function doDatabaseStuff() { const db = await openDB(…);}当然,也可以通过 CDN 引用相关 UMD 依赖直接在浏览器 HTML 中使用:
<script src="https://cdn.jsdelivr.net/npm/idb@8/build/umd.js"></script><script> async function doDatabaseStuff() { const db = await idb.openDB(…); }</script>此时将创建一个全局 idb 对象,其中包含模块版本的所有导出。
idb 常见方法openDB此方法打开一个数据库,并返回一个增强的 IDBDatabase 的 Promise。
const db = await openDB(name, version, { upgrade(db, oldVersion, newVersion, transaction, event) { // … }, blocked(currentVersion, blockedVersion, event) { // … }, blocking(currentVersion, blockedVersion, event) { // … }, terminated() { // … },});deleteDB删除数据库:
await deleteDB(name, { blocked() { // … },});name:数据库的名称。blocked(可选):如果数据库已存在并且存在未响应版本更改事件而关闭的打开连接,则调用该请求,直到它们全部关闭为止。unwrap获取增强的 IndexedDB 对象并返回未修改的普通对象。
const unwrapped = unwrap(wrapped);如果出于某种原因,开发者想返回到普通 IndexedDB 可以使用该方法。,Promise 也将被转换回 IDBRequest 对象。
wrap获取 IDB 对象并返回由此库增强的版本。
const wrapped = wrap(unwrapped);如果某些第三方代码为开发者提供了 IDBDatabase 对象并且希望它具有该库的功能,则这非常有用。
普通增强打开数据库后,API 与 IndexedDB 相同,只是做了一些使事情变得更容易的更改。 首先,任何通常返回 IDBRequest 对象的方法现在都将返回结果的 Promise。
const store = db.transaction(storeName).objectStore(storeName);const value = await store.get(key);该库将所有 IDBRequest 对象转换为 Promise,但它事先并不知道哪些方法可能返回 Promise。因此,诸如 store.put 之类的方法可能会抛出异常而不是返回 Promise。而如果开发者使用异步函数,则没有明显的差异。
Transaction lifetime在 Transaction 开始和结束之间不要 await 其他事情,否则 Transaction 将在完成之前关闭。
如果处理完微任务后没有任何剩余操作,IDB 事务会自动关闭。因此,下面代码能正常工作:
const tx = db.transaction('keyval', 'readwrite');const store = tx.objectStore('keyval');const val = (await store.get('counter')) || 0;await store.put(val + 1, 'counter');await tx.done;但是下面代码却不能:
const tx = db.transaction('keyval', 'readwrite');const store = tx.objectStore('keyval');const val = (await store.get('counter')) || 0;// This is where things go wrong:const newVal = await fetch('/increment?val=' + val);// 这里抛出错误await store.put(newVal, 'counter');await tx.done;idb 的更多方法和使用示例可以参考文末资料,这里不再过多展开。
3.本文总结本文主要和大家介绍 idb ,其是一个很小的(~1.19kB)JavaScript 库,主要包括 IndexedDB API,但有一些小的改进,比如:可用性。因为篇幅问题,关于 idb 主题只是做了一个简短的介绍,但是文末的参考资料提供了大量优秀文档以供学习,如果有兴趣可以自行阅读。如果大家有什么疑问欢迎在评论区留言。
参考资料https://github.com/jakearchibald/idb
https://www.npmjs.com/package/idb
https://web.dev/articles/indexeddb
https://www.mongodb.com/nosql-explained
https://hackernoon.com/use-indexeddb-with-idb-a-1kb-library-that-makes-it-easy-8p1f3yqq
https://blog.openreplay.com/getting-started-with-indexeddb-for-big-data-storage/
https://filipvitas.medium.com/indexeddb-with-promises-and-async-await-3d047dddd313