indexeddb游标遍历海量数据需用opencursor()获取游标,通过continue()分批读取以避免内存溢出;支持idbkeyrange范围筛选、索引查询、分页切片及事务生命周期管理。

IndexedDB 使用游标遍历海量数据,核心是通过 IDBObjectStore.openCursor() 或 IDBIndex.openCursor() 获取游标对象,再用 cursor.continue() 分批读取,避免一次性加载全部数据导致内存溢出或页面卡顿。
创建游标并逐条处理数据
游标默认从第一条记录开始,每次调用 continue() 移动到下一条。适合顺序遍历整个对象存储:
- 调用
objectStore.openCursor()返回一个请求,成功后在onsuccess中获取event.target.result(即游标) - 若游标存在(
cursor !== null),用cursor.value取当前记录,再调用cursor.continue()继续 - 游标走到末尾时,
result为null,递归或循环自然结束
示例:
const transaction = db.transaction('users', 'readonly');
const objectStore = transaction.objectStore('users');
const request = objectStore.openCursor();
request.onsuccess = function(event) {
const cursor = event.target.result;
if (cursor) {
console.log(cursor.value.name); // 处理当前项
cursor.continue(); // 移动到下一项
}
};
按范围或条件限制游标范围
海量数据中常需筛选,可用 IDBKeyRange 控制起始、结束和方向:
-
IDBKeyRange.lowerBound(100):从 key ≥ 100 开始 -
IDBKeyRange.bound(100, 200, true, true):开区间 (100, 200),即 101–199 -
openCursor(range, 'prev'):倒序遍历(注意:仅支持主键或索引字段)
结合索引可高效查询非主键字段:
Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
const index = objectStore.index('age');
const range = IDBKeyRange.bound(18, 65);
const request = index.openCursor(range);
request.onsuccess = function(event) {
const cursor = event.target.result;
if (cursor) {
console.log(cursor.value.name, cursor.value.age);
cursor.continue();
}
};
分页式遍历避免阻塞主线程
一次处理太多条会阻塞 UI,推荐“每批 100 条 + requestIdleCallback”或定时切片:
- 在游标回调中计数,达到阈值后用
setTimeout(() => cursor.continue(), 0)让出线程 - 或使用
requestIdleCallback在浏览器空闲时继续(兼容性需注意) - 更稳妥的做法是手动分页:用
cursor.advance(n)跳过 n 条,配合limit参数模拟分页逻辑
简单切片示例:
let count = 0;
const batchSize = 100;
function handleBatch(cursor) {
if (!cursor || count >= batchSize) {
return; // 暂停,稍后再 resume
}
// 处理 cursor.value...
count++;
cursor.continue();
}
request.onsuccess = function(event) {
const cursor = event.target.result;
if (cursor) {
handleBatch(cursor);
}
};
错误处理与事务生命周期管理
游标依赖事务存活,事务提前结束会导致游标失效:
- 确保游标操作都在事务完成前执行;不要在
transaction.oncomplete后还调用continue() - 监听
transaction.onerror和request.onerror,捕获游标中断(如 DOMException "Transaction inactive") - 必要时重试:保存当前 key,失败后用
openCursor(IDBKeyRange.lowerBound(lastKey))恢复
安全写法:
const transaction = db.transaction('logs', 'readonly');
transaction.onabort = transaction.onerror = () => console.error('Tx failed');
const request = transaction.objectStore('logs').openCursor();
request.onsuccess = function(event) {
const cursor = event.target.result;
if (cursor && transaction.active) { // 显式检查事务状态
processItem(cursor.value);
cursor.continue();
}
};
不复杂但容易忽略。关键是把游标当“迭代器”用,而不是一次性拉全量——它天生为大数据流式处理而设计。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










