如何使用localForage遍历IndexedDB中前缀为field-的存储键
嘿,刚好对这个场景熟!咱们分两种情况来解决,看你的数据量选合适的方法就行~
方案1:简单直接的过滤法(适合小数据集)
localForage 本身提供了 keys() 方法可以获取所有存储的键,我们只需要在拿到所有键之后,过滤出以 field- 开头的就行。这个方法代码简洁,容易维护,适合存储的键数量不多的场景。
async function getFieldKeys() { // 获取所有键 const allKeys = await localForage.keys(); // 过滤出前缀为'field-'的键 return allKeys.filter(key => key.startsWith('field-')); } // 使用示例:拿到键之后遍历操作 getFieldKeys().then(keys => { console.log('找到的field前缀键:', keys); // 遍历每个键获取对应的值 keys.forEach(async key => { const value = await localForage.getItem(key); console.log(`${key} 对应的值:`, value); }); }).catch(err => { console.error('获取键失败:', err); });
方案2:高效的游标范围查询(适合大数据集)
如果你的 IndexedDB 里存储了大量键,全量获取所有键再过滤就有点浪费性能了。这时候可以直接操作 localForage 底层的 IndexedDB 实例,利用游标范围查询来只遍历符合前缀的键,不用加载所有键到内存里。
async function getFieldKeysEfficiently() { return new Promise((resolve, reject) => { // 获取localForage实例 const instance = localForage.getInstance(); // 打开数据库连接 instance.open().then(() => { const db = instance._dbInfo.db; const storeName = instance._dbInfo.storeName; // 创建只读事务 const transaction = db.transaction(storeName, 'readonly'); const store = transaction.objectStore(storeName); // 构建前缀范围:从'field-'到'field-\uffff'(\uffff是Unicode最大字符,确保覆盖所有以field-开头的键) const keyRange = IDBKeyRange.bound('field-', 'field-\uffff', false, false); // 打开游标查询符合范围的键 const cursorRequest = store.openCursor(keyRange); const fieldKeys = []; cursorRequest.onsuccess = (event) => { const cursor = event.target.result; if (cursor) { // 收集符合条件的键 fieldKeys.push(cursor.key); // 继续下一个游标 cursor.continue(); } else { // 游标遍历完成,返回结果 resolve(fieldKeys); } }; cursorRequest.onerror = (event) => { reject(event.target.error); }; }).catch(reject); }); } // 使用示例 getFieldKeysEfficiently().then(keys => { console.log('高效获取的field前缀键:', keys); }).catch(err => { console.error('获取键失败:', err); });
额外优化:同时获取键和值
如果你需要同时拿到键和对应的值,在游标里可以直接获取 cursor.value,不用再单独调用 getItem(),进一步提升效率:
async function getFieldEntries() { return new Promise((resolve, reject) => { const instance = localForage.getInstance(); instance.open().then(() => { const db = instance._dbInfo.db; const storeName = instance._dbInfo.storeName; const transaction = db.transaction(storeName, 'readonly'); const store = transaction.objectStore(storeName); const keyRange = IDBKeyRange.bound('field-', 'field-\uffff', false, false); const cursorRequest = store.openCursor(keyRange); const entries = []; cursorRequest.onsuccess = (event) => { const cursor = event.target.result; if (cursor) { entries.push({ key: cursor.key, value: cursor.value }); cursor.continue(); } else { resolve(entries); } }; cursorRequest.onerror = (event) => { reject(event.target.error); }; }).catch(reject); }); }
注意事项
- 方案2直接用到了 localForage 的内部属性(
_dbInfo),虽然目前主流版本都兼容,但如果未来 localForage 更新底层实现,可能会失效。如果你的项目需要长期稳定,优先选方案1;如果性能是核心需求,可以用方案2并做好版本测试。 - 两种方法都支持
async/await,记得做好错误捕获,避免未处理的Promise异常。
内容的提问来源于stack exchange,提问作者H. K.
相关产品推荐
相关产品推荐

