向IndexedDB插入数据报错:执行put时提示事务已完成
解决IndexedDB中"Failed to execute 'put' on 'IDBObjectStore': The transaction has finished"错误
嘿,这个报错我太熟了!本质上是IndexedDB的事务机制在搞鬼,咱们一步步拆解问题:
问题原因
IndexedDB的事务有个「自动提交」的特性:当你创建事务后,如果当前事件循环队列里没有待处理的异步操作,浏览器会自动把事务提交关闭。
看你的代码流程:
- 在
request.onsuccess里创建了读写事务tx - 调用
displayData并传入回调oncompleted request.onsuccess的回调函数执行完毕,主线程回到事件循环- 这时候事务没有等待任何异步任务,直接被浏览器自动提交关闭了
- 等
oncompleted回调执行,再调用store.put时,事务已经凉透了,自然就报错了
解决方案
根据displayData的实际逻辑(同步/异步),有两种靠谱的处理方式:
方案1:如果displayData是异步操作(比如有网络请求、定时器)
这种情况要让事务等待异步操作完成,咱们可以用Promise把异步逻辑包装起来,配合async/await让事务保持活跃:
request.onsuccess = async function(e) { var ip="kaka"; console.log("success"); db = request.result; // 先开启事务 const tx = db.transaction("List","readwrite"); const store = tx.objectStore("List"); const index = store.index("Name"); // 用Promise包装displayData的异步逻辑,等待结果返回 const value = await new Promise((resolve) => { displayData(function oncompleted(val) { console.log('The value is', val); resolve(val); }); }); // 现在事务还活着,放心执行put操作 store.put({ Name: $('#card').val(), IP: value }); // 可选:监听事务的完成/错误状态,方便调试 tx.oncomplete = () => console.log("数据插入成功,事务已提交"); tx.onerror = (err) => console.error("事务出错啦:", err); } function displayData(myCallbackFunction) { // 举个异步例子:模拟网络请求 setTimeout(() => { const set = "your-actual-value"; // 替换成你的真实数据 myCallbackFunction(set); }, 100); }
方案2:如果displayData是同步操作
那咱们调整一下执行顺序,先拿到value,再创建事务执行put,确保所有操作都在同一事件循环里完成,不给事务提前提交的机会:
request.onsuccess = function(e) { var ip="kaka"; console.log("success"); db = request.result; // 先同步拿到需要的value let value; displayData(function oncompleted(val) { console.log('The value is', val); value = val; }); // 再创建事务并执行put const tx = db.transaction("List","readwrite"); const store = tx.objectStore("List"); const index = store.index("Name"); store.put({ Name: $('#card').val(), IP: value }); tx.oncomplete = () => console.log("事务顺利完成"); } function displayData(myCallbackFunction) { // 同步逻辑示例 const set = "your-actual-value"; myCallbackFunction(set); }
小提示
- IndexedDB的事务是「短命鬼」,一定要确保所有事务内的操作都在事务活跃期间完成
- 别把事务创建放在全局或者长期存活的上下文里,用完就提交才是正确姿势
内容的提问来源于stack exchange,提问作者shaswat kumar
相关产品推荐
相关产品推荐

