Firebase:Flutter:避免事务崩溃 CloudFirestorePlugin.java:613 : .then() vs async/await

Posted

技术标签:

【中文标题】Firebase:Flutter:避免事务崩溃 CloudFirestorePlugin.java:613 : .then() vs async/await【英文标题】:Firebase: Flutter: Avoiding Transaction crashes CloudFirestorePlugin.java:613 : .then() vs async/await 【发布时间】: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() 调用。

这是有道理的,强制写入仅在获取完成后发生。然而,*** 上的某个人建议我应该在事务中使用 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

【问题讨论】:

【参考方案1】:

从 Flutter 到 Firebase 的交易似乎有一些严重的问题:https://github.com/FirebaseExtended/flutterfire/issues/1969 通过类似的线索,这些问题似乎已经持续了六个多月。我很惊讶地发现,虽然 Firebase 和 Flutter 都是 Google 产品,但它们之间的通信并不是 Google 产品。

此时,如果您有一个依赖于许多事务的高度活跃的数据库应用程序,您可能会遇到这些崩溃。许多旨在保护交易的核心机制似乎是导致交易失败的原因。

我正在决定如何继续前进,但看起来我将不得不使用混合的解决方案并删除大部分,可能是所有我的 runTransaction 调用。

如果出现以下情况,交易可能会严重失败:

    事务需要重试。 来自多个客户端的两个并行事务发生。 从一个客户到不同位置的两笔交易紧随其后。 从一个客户端执行相同的事务,紧接其上一次调用。

即使您是使用 async/await 或 .then() 调用的圣人,这些问题仍然存在。

请...如果我错了,请有人纠正我。

【讨论】:

以上是关于Firebase:Flutter:避免事务崩溃 CloudFirestorePlugin.java:613 : .then() vs async/await的主要内容,如果未能解决你的问题,请参考以下文章

添加flutter_firebase_ui后flutter应用程序崩溃

使用带有 Firebase 身份验证的 ProGuard 构建 Flutter 崩溃

添加flutter firebase auth ui后应用程序崩溃

如何使用 Flutter 执行 Firebase 可变事务数据?

Flutter Firebase 身份验证与 Google 应用程序崩溃

如何使 Android 和 iOS 的 Flutter App 崩溃(以测试 Firebase Crashlytics)?