求助:IndexedDB中orderProductIndex索引下多条记录批量更新失败
解决IndexedDB批量更新多条记录的问题
第一次尝试的问题与修复
你的第一个方案无效,核心问题有两个:
- 循环外的
resolve()会提前结束Promise,此时所有put异步请求还未执行完成; - 循环内每次
put成功都调用resolve(),会导致Promise被多次resolve,不符合Promise规范。
修正后的代码:
index.getAll([order_id, product_id]).onsuccess = (event) => { const updatePromises = []; $.each(event.target.result, function (index, item) { item.timestamp = Date.now(); // 将每个put请求包装成Promise updatePromises.push(new Promise((resolvePut) => { const putRequest = objectStore.put(item); putRequest.onsuccess = function (event) { console.log('item updated') console.log(event.target.result) resolvePut(); }; // 处理更新失败的情况 putRequest.onerror = function (event) { console.error('update failed', event); resolvePut(); }; })); }); // 等待所有更新完成后再resolve Promise.all(updatePromises).then(() => resolve()); }
第二次尝试的问题与修复
你的游标方案陷入无限循环,是因为cursor.update是异步操作,你在调用它之后立刻执行cursor.continue(),会导致游标在更新操作完成前就移动,破坏了游标的遍历逻辑。正确的做法是在cursor.update的onsuccess回调里调用cursor.continue(),确保当前记录更新完成后再遍历下一条。
修正后的代码:
let index = objectStore.index("orderProductIndex"); let keyRange = IDBKeyRange.only([order_id, product_id]); let request = index.openCursor(keyRange); request.onsuccess = function (event) { console.log('cursor opened'); let cursor = event.target.result; if (cursor) { let record = cursor.value; record.timestamp = Date.now(); console.log(record); // 在update的成功回调里继续游标 let updateRequest = cursor.update(record); updateRequest.onsuccess = function() { cursor.continue(); }; // 处理更新失败的情况,避免游标停滞 updateRequest.onerror = function(event) { console.error('update failed', event); cursor.continue(); }; } else { console.log('end'); resolve(); } }
额外提示
- 无论哪种方案,都要处理请求失败的情况,避免流程卡住;
- 游标方案的性能通常比
getAll后遍历更好,尤其是当记录数量较多时,推荐使用游标方案。
内容的提问来源于stack exchange,提问作者Telexx
相关产品推荐
相关产品推荐

