IndexedDB需先open再onupgradeneeded中建objectStore;写操作必须在事务内同步完成,避免await导致事务关闭;读取主键用get(),查字段需先建索引;错误须监听request.onerror而非transaction。

如何打开 IndexedDB 并创建 objectStore
IndexedDB 不是直接可用的数据库,必须先请求打开连接,再在升级时定义 objectStore(类似表)。如果数据库已存在,onupgradeneeded 只会在版本号升高时触发——这点常被忽略,导致新增 objectStore 失败却无报错。
实操建议:
- 始终检查
event.oldVersion和event.newVersion,避免重复创建objectStore - 用
db.createObjectStore('users', { keyPath: 'id' })指定主键路径;若数据无固定 ID,可设autoIncrement: true - 不要在
onsuccess里建objectStore,它只读,升级必须在onupgradeneeded中完成
如何添加数据到 objectStore
写操作必须在事务中进行,且事务生命周期极短——一旦事件循环空闲,事务自动关闭。常见错误是把 add() 放在异步回调(如 fetch().then())里,此时事务早已结束,报错 TransactionInactiveError。
实操建议:
- 用
transaction.objectStore('users').add({ id: 1, name: 'Alice' })添加单条;批量用循环调用add(),别攒成数组再统一提交 - 务必监听
request.onsuccess和request.onerror,失败时event.target.error会给出具体原因(如ConstraintError表示主键冲突) - 若需覆盖同 key 数据,改用
put()而非add()
如何按主键或索引读取数据
读取分两种典型场景:精确查(主键)和范围查(索引)。直接用 get() 最快,但只能靠 key;想按其他字段查(如 email),必须提前在 onupgradeneeded 中用 store.createIndex('emailIdx', 'email') 建索引。
生成可在 deepbi 沙箱 iframe 内运行或作为独立文件运行的交互式 HTML 页面,使用 `window.deepbi` JS SDK 实现数据查询、空间管理、文件浏览及用户操作。当用户提出以下需求时启用该能力: - 创建 KPI 仪表盘、数据表格、文件浏览器、成员列表、管理页面; - 明确要求“转成 dhtml”、“转译成 HTML”、“把 XX 页面转成……”、“控制台页面”、“管理后台”、“DeepBI 页面迁移”; - 提及位于 `apps/console/src/featur
实操建议:
-
store.get(1)返回 Promise-like 的IDBRequest,结果在request.result,不是返回值 - 用索引查:先
store.index('emailIdx').get('a@b.com'),注意索引名必须和创建时完全一致 - 范围查询用
IDBKeyRange.bound('a', 'z'),但记得openCursor()或getAll()才真正执行;getAll()在大量数据时可能内存溢出,慎用
为什么 transaction 会突然失效?
这是最隐蔽也最常踩的坑:IndexedDB 的事务不是“手动 commit”,而是由事件循环控制。只要没显式阻塞 JS 执行,事务在当前任务结束时就关闭。这意味着 await fetch() 后再调用 add() 必然失败——因为中间穿插了微任务和渲染帧。
实操建议:
- 所有数据库操作必须包裹在同一事务内,包括获取数据、处理逻辑、写入结果
- 需要异步前置数据时(如先 fetch 再存),把 DB 操作放在
fetch().then(() => { /* 事务内 add */ }),而非await fetch(); /* 此处事务已死 */ - 用
transaction.oncomplete做事后清理,但别指望它能捕获写入错误——错误发生在 request 级别,不是 transaction 级别
IndexedDB 的复杂性不在 API 多,而在它的事务模型和事件驱动机制与现代 async/await 风格天然冲突。写的时候多看 transaction.state 和 request.readyState,比反复试错快得多。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










