【发布时间】:2020-09-21 05:55:39
【问题描述】:
由于事务和侦听器,我的应用最近不断崩溃。我想确保在我带领十字军修复这些系统之前正确使用事务。
INTERNAL ASSERTION FAILED: A transaction object cannot be used after its update callback has been invoked.
io.flutter.plugins.firebase.cloudfirestore.CloudFirestorePlugin$5.doInBackground
从逻辑上讲,这个错误让我相信,不知何故,在单个事务中,无论是立即还是在重试期间,标识该事务的某些密钥处理不当。我遇到了一篇有趣的帖子,其中“声称的解决方案”是在 transaction.get(doc) 之后从 async/await 切换到 .then() 调用。
这是有道理的,强制写入仅在获取完成后发生。然而,StackOverflow 上的某个人建议我应该在事务中使用 async/await,而不是我最初在所有地方使用的 .then()。
我想确保我做的另一件事是返回与交易相关的正确未来。我见过无数不同回报的例子,有些根本没有回报。
为了稳定而使用交易的正确方法是什么?
1) 我当前的方法示例:
List<String> _activeTransactionUpdate = [];
Future transactionUpdateSet(
{@required DocumentReference docRef, @required Map<String, dynamic> payload, bool forceSet = false})
{
if (_activeTransactionUpdate.contains(docRef.path)) {
printRed('**********TRANSATION UPDATE DUPLICATE**********\n${docRef.path}');
return Future.delayed(Duration(seconds: 4));
}
return Firestore.instance.runTransaction((t) async {
var doc = await t.get(docRef);
return doc.exists
? t.update(docRef, payload)
: forceSet ? t.set(docRef, payload) : t.update(docRef, {});
}).then((_) => _activeTransactionUpdate.remove(docRef.path));
}
2) 建议的方法示例
List<String> _activeTransactionUpdate = [];
Future transactionUpdateSet(
{@required DocumentReference docRef, @required Map<String, dynamic> payload, bool forceSet = false})
{
if (_activeTransactionUpdate.contains(docRef.path)) {
printRed('**********TRANSATION UPDATE DUPLICATE**********\n${docRef.path}');
return Future.delayed(Duration(seconds: 4));
}
return Firestore.instance.runTransaction((t) {
return t.get(docRef).then((doc) {
return doc.exists
? t.update(docRef, payload)
: forceSet ? t.set(docRef, payload) : t.update(docRef, {});
});
}).then((_) => _activeTransactionUpdate.remove(docRef.path));
}
仅供参考,我使用事务映射密钥检查器来确保一个客户端不会多次尝试同时更新给定文档。
编辑:QQhttps://github.com/FirebaseExtended/flutterfire/issues/1969
【问题讨论】:
标签: firebase flutter asynchronous