IndexedDB 游标不直接检测变更,而是通过 openCursor() 遍历待同步记录、结合 IDBKeyRange 限定范围、依托 updatedAt 索引实现增量同步,需配合事务隔离与元数据设计。

HTML5 中游标(Cursor)本身并不直接参与离线数据同步或变更检测——这是常见误解。真正起作用的是 IndexedDB 的游标机制,配合事务、版本升级和键范围查询,实现对本地数据库变更的高效遍历与比对。它不主动“检测”变更,而是为开发者提供按序访问、增量同步所需数据的能力。
游标在 IndexedDB 同步流程中的角色
在离线优先应用中,同步通常分三步:采集本地变更、上传至服务端、拉取远程更新。游标主要用于第一步和第三步的数据遍历:
- 用
openCursor()遍历所有待同步的记录(如标记为status: "pending"的数据) - 结合
IDBKeyRange.bound()限定时间范围(如lastSyncTime之后的记录),避免全表扫描 - 在读取每条记录时,可同时检查其
updatedAt时间戳或version字段,判断是否需上传或覆盖本地
用游标识别新增/修改/删除操作
IndexedDB 本身不记录操作类型,需靠业务字段或元数据设计支撑变更识别:
-
新增:查找
id不存在于服务端响应中的本地记录(需先拉取远程 ID 列表,再用游标比对) -
修改:游标遍历时对比本地
updatedAt与服务端返回对应记录的时间戳,取较新者生效 -
删除:服务端返回已删除 ID 列表后,用游标 +
delete()批量清除本地对应项(注意:需在只读事务外执行)
避免常见陷阱:游标生命周期与事务一致性
游标强依赖事务生命周期,一旦事务提交或中止,游标立即失效:
立即学习“前端免费学习笔记(深入)”;
- 不要跨事务复用游标;每次同步操作应开启独立事务(
readwrite模式用于写,readonly用于读) - 大量数据同步时,避免单次游标遍历过久导致事务超时;可用
continue()分片处理,并在每次迭代后手动commit或使用递归+延时控制 - 游标默认按主键升序遍历;若需按更新时间排序,应将
updatedAt设为索引(createIndex("byUpdatedAt", "updatedAt")),再用该索引打开游标
轻量替代方案:不总需要游标
简单场景下,游标并非唯一选择:
- 仅需获取所有待同步记录?用
getAll()更简洁(但注意内存占用,大数据集慎用) - 只查某一条最新变更?用
get()或带limit(1)的索引查询即可 - 纯时间戳比对同步?可在服务端返回
lastServerTime,客户端用索引游标只读取该时间之后的记录,无需逐条校验
游标不是银弹,而是 IndexedDB 提供的底层遍历工具。能否高效支撑离线同步,关键在于索引设计、事务划分和变更元数据的合理约定。


















