Flutter/cloud-firestore“任务已经完成”异常

Posted

技术标签:

【中文标题】Flutter/cloud-firestore“任务已经完成”异常【英文标题】:Flutter/cloud-firestore "Task is already complete" Exception 【发布时间】:2019-01-20 17:55:14 【问题描述】:

我正在使用 Flutter 编写应用程序,我必须使用 Firestore.instance.runTransaction(Transaction tx) 方法进行交易。 在我的 Transaction 对象(或方法)中,我必须使用文档引用更新一些数据。

_firestore.runTransaction((Transaction x) async 
  await x.update(Aref, 'data': itemA - y);
  await x.update(Bref, 'data': itemB + y);
)

代码运行时会抛出异常(这里是控制台日志):

E/MethodChannel#plugins.flutter.io/cloud_firestore(32612):方法调用结果处理失败 E/MethodChannel#plugins.flutter.io/cloud_firestore(32612): java.lang.IllegalStateException: 任务已经完成 E/MethodChannel#plugins.flutter.io/cloud_firestore(32612):在 com.google.android.gms.common.internal.Preconditions.checkState(未知来源:8) E/MethodChannel#plugins.flutter.io/cloud_firestore(32612):在 com.google.android.gms.tasks.zzu.zzdr(未知来源:8) E/MethodChannel#plugins.flutter.io/cloud_firestore(32612):在 com.google.android.gms.tasks.zzu.setResult(未知来源:3) E/MethodChannel#plugins.flutter.io/cloud_firestore(32612):在 com.google.android.gms.tasks.TaskCompletionSource.setResult(未知来源:2) E/MethodChannel#plugins.flutter.io/cloud_firestore(32612):在 io.flutter.plugins.firebase.cloudfirestore.CloudFirestorePlugin$3$1.success(CloudFirestorePlugin.java:283) E/MethodChannel#plugins.flutter.io/cloud_firestore(32612):在 io.flutter.plugin.common.MethodChannel$IncomingResultHandler.reply(MethodChannel.java:169) E/MethodChannel#plugins.flutter.io/cloud_firestore(32612):在 io.flutter.view.FlutterNativeView.handlePlatformMessageResponse(FlutterNativeView.java:187) E/MethodChannel#plugins.flutter.io/cloud_firestore(32612):在 android.os.MessageQueue.nativePollOnce(Native Method) E/MethodChannel#plugins.flutter.io/cloud_firestore(32612):在 android.os.MessageQueue.next(MessageQueue.java:325) E/MethodChannel#plugins.flutter.io/cloud_firestore(32612):在android.os.Looper.loop(Looper.java:142)

【问题讨论】:

有同样的问题。我想我已经在一段时间前的某个时间提出了一个问题并在这里提出了一个问题,但我似乎找不到它。 我遇到了类似的问题,虽然我也遇到了你的问题:***.com/questions/51051730/… 【参考方案1】:

当同时多次调用firestore api时会发生错误,您必须将每个函数嵌套在 前一个函数的“whenComplete(() ”方法。 这是错误代码:

g.f.runTransaction((transaction) async 
      DocumentSnapshot snap =
          await transaction.get(/my code);

      await transaction.update(/my code).whenComplete(() );
    );


g.f.runTransaction((transaction) async 
      DocumentSnapshot freshSnap =
              await transaction.get(/my code));

      await transaction.update(/my code).whenComplete(() );
);  //here is the problem!! I'have to nest this inside "whenComplete(() )

这是错误:

E/MethodChannel#plugins.flutter.io/cloud_firestore(5337): 失败 处理方法调用结果 E/MethodChannel#plugins.flutter.io/cloud_firestore(5337): java.lang.IllegalStateException: 任务已经完成

这是正确的代码

g.f.runTransaction((transaction) async 
  DocumentSnapshot snap =
      await transaction.get(/my code);

  await transaction.update(/my code).whenComplete(() 
    g.f.runTransaction((transaction) async 
      DocumentSnapshot freshSnap =
          await transaction.get(/my code);

      await transaction.update(/my code);
    ).whenComplete(() );
  );
);

【讨论】:

这绝对不是问题的原因(对我来说)。因为我仍然遇到问题并且我没有使用您的“错误代码”。 @creativecreatorormaybenot 检查是否同时有另一个对 firestore 的调用,例如“document ().update ()”或类似的东西 不,没有。你是根据什么来了解这些知识的?我看不出并发操作不起作用的原因,而且并发运行这些操作并不容易,因为它们不需要很长时间来执行。 我遇到了同样的错误并为我工作,也许还有其他原因导致同样的错误 没有理由同时调用whenComplete,它只会破坏runTransaction 的含义,但它可能对你有用,因为截至目前runTransaction 中存在一个错误,所以这些并发调用只是短期解决方案。【参考方案2】:

我遇到了同样的问题。尝试这个。希望能帮助到你 FIrestore Transaction Handler

Firestore 事务处理程序

当在cloud_firestore pub 中为Flutter 使用runTransaction 函数时,这是一个帮助处理失败事务问题的子例程

问题

此代码是 Flutter 的 cloud_firestore 包错误的解决方案,用于以下错误 1.PlatformException(Error performing Transaction#get, Transaction has already completed., null) 2.DoTransaction failed: Document version changed between two reads.

根据我的经验,我意识到当我尝试更新刚刚创建的记录时会出现问题。 由于某种原因,tx.get()(参见https://pub.dev/packages/cloud_firestore 中runTransaction 的示例)无法获取刚刚创建的记录,并且更新操作失败。 我发现如果我们稍等片刻再试一次,我们将能够获取记录并更新它。 为方便起见,我创建了一个为您执行更新和运行事务的函数。

解决方案

这是一个例子:

     await fcmTransactionHandler(
      postRef: postRef, //  This is your DocumentReference that you want to update
      key: 'myfield', // This is the field that you want to update
      validationFunction: updateMyField, // This is a function that allows you to check 
      // some condition in the record you 'get' before updating
 );

validationFunction 将动态值(您要更新的字段的值)作为输入,并给出您将在记录中更新的 值。 例如,如果我想更新一个字段myfield,如果它是true,那么我将创建一个函数updateMyField,如下所示

Map<String, dynamic> updateMyField(dynamic value) 
    return  value ? <String, dynamic>'myfield': true : <String, dynamic>'myfield': value;
  

然后这个函数被传递给validationFunction。 为什么要这样设计? 如您所见,我们正在尝试在一段时间后获取记录,然后对其进行更新。如果记录已被其他人更新了怎么办? 在这种情况下,我们必须在记录可供我们使用时验证我们获得的数据,以防止任何不正确的更新。 validationFunction 帮助我们做到这一点。

【讨论】:

以上是关于Flutter/cloud-firestore“任务已经完成”异常的主要内容,如果未能解决你的问题,请参考以下文章

如何将网址设为可信任站点

linux配置静态ip只能ping通同网段任何地址

为啥json没有做任何事情?

更新云功能后看不到任何日志

Mongo突然关闭,没有任何日志

为啥 .catch() 没有做任何事情?