get和getAll是IndexedDB中按主键精确检索的高效方法:get(key)单条获取,getAll([keys])批量获取,均需在只读事务中调用,性能近O(1),但不支持范围或模糊查询。

IndexedDB 的 get 和 getAll 方法是按主键(key)检索数据最直接、高效的方式,适用于已知主键值的场景。它们不走索引,直接定位到对象存储(objectStore)中对应记录,性能接近 O(1)。
get 方法:精准获取单条记录
get(key) 用于根据精确的主键值读取一条记录。它返回一个 IDBRequest 对象,成功时 result 即为匹配的数据(若无匹配则为 undefined)。
使用要点:
- 主键必须完全匹配(类型和值都一致),比如主键是数字
123,传字符串"123"就查不到 - 适合已知唯一 ID 的场景,如加载用户详情页时按
userId取数据 - 不支持范围查询或模糊匹配,仅限单值精确查找
示例:
立即学习“Java免费学习笔记(深入)”;
const transaction = db.transaction(['users'], 'readonly');
const store = transaction.objectStore('users');
const request = store.get(1001); // 主键是 number 类型的 1001
request.onsuccess = function () {
const user = request.result;
if (user) {
console.log('找到用户:', user.name);
} else {
console.log('未找到 ID 为 1001 的用户');
}
};
getAll 方法:批量获取多条指定主键的记录
getAll(keys) 接收一个主键数组(如 [1001, 1002, 1005]),一次性返回所有匹配记录的数组,顺序与 keys 数组一致。注意:它不会跳过不存在的 key,缺失项在结果中为 undefined(不是被过滤掉)。
适用场景:
- 需要按 ID 列表批量加载数据(如评论列表中按
commentIds拉取作者信息) - 主键集合已知且数量适中(通常建议不超过几百个,避免阻塞主线程)
- 比循环调用
get更高效,减少事务开销和事件调度次数
示例:
立即学习“Java免费学习笔记(深入)”;
const request = store.getAll([1001, 1002, 9999]); // 9999 不存在
request.onsuccess = function () {
const results = request.result; // [user1, user2, undefined]
results.forEach((user, i) => {
if (user) console.log(`ID ${[1001,1002,9999][i]}:`, user.name);
});
};
关键注意事项
这些方法虽快,但需避开几个常见坑:
-
必须在只读事务中调用:即使只是读取,也要显式开启
'readonly'事务,不能在数据库打开回调里直接调用 -
主键路径要对得上:如果 objectStore 使用了
keyPath(如{ keyPath: 'id' }),那么主键就是数据对象的id字段值;若用autoIncrement: true,主键是自增数字,不能传其他字段 - getAll 不保证顺序稳定?:实际行为中,Chrome/Firefox 均按输入 keys 顺序返回,但规范未强制要求——生产环境建议自行按 keys 映射校验,不要依赖隐式顺序
- 大数据量慎用 getAll:一次取几百条没问题,但若传入上千个 key,可能触发内存压力或长时间运行,此时应考虑分批或改用游标(cursor)+ keyRange
替代方案:当 get / getAll 不够用时
如果需求超出主键精确匹配能力(比如“查所有 status 为 active 的用户”),就不能用 get 或 getAll,而要:
- 在 objectStore 上创建二级索引(如
store.createIndex('by_status', 'status')),再用index.get()或index.getAll() - 用
openCursor()配合IDBKeyRange做范围查询(如IDBKeyRange.bound(1000, 2000)) - 避免全表扫描:不在索引字段上查询时,IndexedDB 会遍历全部记录,性能急剧下降


















