打开IDBObjectStore触发DOMException:事务已完成问题求助
解决IndexedDB事务完成后无法获取ObjectStore的DOMException错误
错误原因分析
错误提示Failed to execute 'objectStore' on 'IDBTransaction': The transaction has finished的核心问题是:你在事务已经结束的时机去调用objectStore()方法。
IndexedDB的事务有明确的生命周期:当onComplete事件触发时,事务已经提交并释放了所有关联资源,此时再尝试访问事务内的ObjectStore会被拒绝。你的代码错误地套用了处理db.Request的逻辑——Request的onSuccess是请求完成、结果可用的时机,但Transaction的onComplete是事务结束的信号,不是获取资源的节点。
修正后的代码
调整completeTransaction函数的逻辑,在事务活跃时立即获取ObjectStore,再通过事务的事件确认状态:
Future<db.ObjectStore> completeTransaction( final db.Transaction transaction, final String objectStoreName, ) { final Completer<db.ObjectStore> completer = Completer<db.ObjectStore>.sync(); // 事务创建后立即获取ObjectStore(此时事务处于活跃状态,合法) final db.ObjectStore objectStore = transaction.objectStore(objectStoreName); // 监听事务错误,将错误传递给completer transaction.onError.listen(completer.completeError); // 事务完成时,返回已获取的ObjectStore transaction.onComplete.listen((_) { completer.complete(objectStore); }); return completer.future; }
关键逻辑说明
- 时机调整:在事务刚创建(
database.transactionStore返回的是活跃事务)时,直接调用transaction.objectStore()获取ObjectStore,这是符合IndexedDB规范的操作时机。 - 事件绑定:通过
onError监听事务执行中的错误,通过onComplete确认事务顺利完成,最终将已准备好的ObjectStore返回给调用方。 - 区别Request与Transaction:原
_completeRequest函数处理的是单次请求,onSuccess是请求结果就绪的信号;而Transaction代表的是一组操作的集合,onComplete是整个操作集合结束的通知,两者的生命周期逻辑完全不同,不能直接复用代码结构。
调用方式说明
你的原有调用方式不需要修改,因为database.transactionStore返回的是刚创建的活跃事务,传递给修正后的函数可以直接获取到合法的ObjectStore:
void main() async { ... await completeTransaction( database.transactionStore(objectStoreName, "readwrite"), objectStoreName, ); ... }
内容的提问来源于stack exchange,提问作者gitman-2021
相关产品推荐
相关产品推荐

