indexeddb纯异步,无同步api,所有操作必须通过事件或promise封装;需规避伪同步陷阱,分块事务(100–500条/批)、游标分页、主动让出主线程以保ui流畅。

IndexedDB 本身是纯异步的,所有数据库操作(打开、读写、索引查询、事务提交)都通过事件或 Promise 封装,天然不阻塞主线程。所谓“同步异步调度”,其实不是在 IndexedDB 内部做同步/异步切换,而是开发者需主动规避伪同步陷阱和不当的批量操作模式,确保高频率或大数据量场景下仍保持 UI 流畅。
✅ 正确理解:IndexedDB 没有同步 API
浏览器明确不提供 indexedDB.openSync 或 store.getSync 这类接口。所有操作必须走 request.onsuccess、transaction.oncomplete 或现代封装中的 await(基于 Promise 包装)。如果你看到“同步行为”,大概率是以下原因:
- 在
onsuccess回调里执行了大量计算或 DOM 操作 - 用
while(cursor)手动遍历游标但未分片,导致单次循环耗时过长 - 在一个事务中塞入成千上万条
add(),让事务长时间占用资源
⚙️ 关键调度策略:控制节奏,拆分负载
避免大事务堆积
- 单个事务建议控制在 100–500 条写入以内
- 超过可拆分为多个事务,用递归或队列控制节奏
async function batchAdd(items, chunkSize = 200) {
for (let i = 0; i setTimeout(r, 0)); // 让出主线程,防卡顿
}
}
游标遍历务必分页或限流
- 不要一次性
openCursor()后.continue()到底 - 改用
openCursor({ limit: 100 })+ 递归加载,或监听cursor.continue()完成后再继续
读操作也需节制
-
getAll()适合小数据集( - 查询带索引的字段(如
index.getAll(IDBKeyRange.bound(...)))比全表扫描高效得多
? 配合主线程友好机制
-
用
setTimeout(fn, 0)或queueMicrotask()主动让出控制权,尤其在循环或递归中 -
结合
requestIdleCallback处理低优先级后台同步任务(如离线数据回传) - 对非关键路径操作加 loading 状态或骨架屏,避免用户感知延迟
❗ 特别注意:事务生命周期与错误传播
- 事务在最后一个请求完成且无未处理错误时自动提交;任一请求
onerror会回滚整个事务 - 不要在事务外保留
objectStore引用——它随事务结束失效 - 错误未捕获会导致事务静默失败,建议统一包装
.catch()并打日志
基本上就这些。IndexedDB 的异步性是它的底座优势,真正影响体验的,是你怎么组织请求节奏和事务边界。











