简体   繁体   English

Flutter / cloud-firestore“任务已经完成”例外

[英]Flutter/cloud-firestore “Task is already complete” Exception

I'm writing an app using Flutter and i have to make a transaction using the Firestore.instance.runTransaction(Transaction tx) method. 我正在使用Flutter编写应用程序,我必须使用Firestore.instance.runTransaction(Transaction tx)方法进行Firestore.instance.runTransaction(Transaction tx) In my Transaction object (or method) i have to update some data using the document reference. 在我的Transaction对象(或方法)中,我必须使用文档引用更新一些数据。

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

When the code is running it throw an exception (Here the console log): 代码运行时抛出异常(这里是控制台日志):

E/MethodChannel#plugins.flutter.io/cloud_firestore(32612): Failed to handle method call result E/MethodChannel#plugins.flutter.io/cloud_firestore(32612): java.lang.IllegalStateException: Task is already complete E/MethodChannel#plugins.flutter.io/cloud_firestore(32612): at com.google.android.gms.common.internal.Preconditions.checkState(Unknown Source:8) E/MethodChannel#plugins.flutter.io/cloud_firestore(32612): at com.google.android.gms.tasks.zzu.zzdr(Unknown Source:8) E/MethodChannel#plugins.flutter.io/cloud_firestore(32612): at com.google.android.gms.tasks.zzu.setResult(Unknown Source:3) E/MethodChannel#plugins.flutter.io/cloud_firestore(32612): at com.google.android.gms.tasks.TaskCompletionSource.setResult(Unknown Source:2) E/MethodChannel#plugins.flutter.io/cloud_firestore(32612): at io.flutter.plugins.firebase.cloudfirestore.CloudFirestorePlugin$3$1.success(CloudFirestorePlugin.java:283) E/MethodChannel#plugins.flutter.io/cloud_firestore(32612): at io.flutter.plugin.common.MethodC 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):at com.google.android.gms.common.internal.Preconditions.checkState(Unknown来源:8)E / MethodChannel#plugins.flutter.io / cloud_firestore(32612):at com .google.android.gms.tasks.zzu.zzdr(未知来源:8)E / MethodChannel#plugins.flutter.io / cloud_firestore(32612):at com.google.android.gms.tasks.zzu.setResult(Unknown Source :3)E / MethodChannel#plugins.flutter.io / cloud_firestore(32612):at com.google.android.gms.tasks.TaskCompletionSource.setResult(Unknown来源:2)E / MethodChannel#plugins.flutter.io / cloud_firestore( 32612):at io.flutter.plugins.firebase.cloudfirestore.CloudFirestorePlugin $ 3 $ 1.success(CloudFirestorePlugin.java:283)E / MethodChannel#plugins.flutter.io / cloud_firestore(32612):at io.flutter.plugin.common。 MethodC hannel$IncomingResultHandler.reply(MethodChannel.java:169) E/MethodChannel#plugins.flutter.io/cloud_firestore(32612): at io.flutter.view.FlutterNativeView.handlePlatformMessageResponse(FlutterNativeView.java:187) E/MethodChannel#plugins.flutter.io/cloud_firestore(32612): at android.os.MessageQueue.nativePollOnce(Native Method) E/MethodChannel#plugins.flutter.io/cloud_firestore(32612): at android.os.MessageQueue.next(MessageQueue.java:325) E/MethodChannel#plugins.flutter.io/cloud_firestore(32612): at android.os.Looper.loop(Looper.java:142) hannel $ IncomingResultHandler.reply(MethodChannel.java:169)E / MethodChannel#plugins.flutter.io / cloud_firestore(32612):at 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):at android.os.MessageQueue.next(MessageQueue.java:325 )E / MethodChannel#plugins.flutter.io / cloud_firestore(32612):at android.os.Looper.loop(Looper.java:142)

The error happens when there are multiple call to the firestore api concurrently, you have to nest each funcion inside the "whenComplete(() {}" method of the previous function. This is the wrong code : 当同时多次调用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(() {})

this is the error: 这是错误:

E/MethodChannel#plugins.flutter.io/cloud_firestore( 5337): Failed to handle method call result E/MethodChannel#plugins.flutter.io/cloud_firestore( 5337): java.lang.IllegalStateException: Task is already complete E / MethodChannel#plugins.flutter.io / cloud_firestore(5337):无法处理方法调用结果E / MethodChannel#plugins.flutter.io / cloud_firestore(5337):java.lang.IllegalStateException:任务已完成

this is right code 这是正确的代码

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(() {});
  });
});

I had the same problem. 我有同样的问题。 Try this. 试试这个。 Hope it Helps FIrestore Transaction Handler 希望它有助于FIrestore事务处理程序

Firestore-Transaction-Handler 公司的FireStore-事务处理程序

This is a subroutine to help handle the failing transaction issue when using runTransaction function in cloud_firestore pub for Flutter 这是一个子程序,用于在cloud_firestore pub中为Flutter使用runTransaction函数时帮助处理失败的事务问题

The Problem 问题

This code is a solution to errors with cloud_firestore package for Flutter for the following errors 1. PlatformException(Error performing Transaction#get, Transaction has already completed., null) 2. DoTransaction failed: Document version changed between two reads. 对于以下错误,此代码是针对Flutter的cloud_firestore包的错误的解决方案1. PlatformException(Error performing Transaction#get, Transaction has already completed., null) DoTransaction failed: Document version changed between two reads.

From my experience, I realized that the issue occurs when I try to update a record which was only just created. 根据我的经验,我意识到当我尝试更新刚刚创建的记录时会出现问题。 For some reason the tx.get() (see the example for runTransaction in https://pub.dev/packages/cloud_firestore ) is unable to get the record that was just created and the update operation fails. 出于某种原因, tx.get() (请参阅https://pub.dev/packages/cloud_firestore中的 runTransaction示例)无法获取刚刚创建的记录,并且更新操作失败。 I found that if we wait for a bit and try again, we will be able to get the record and update it. 我发现如果我们等一下再试一次,我们就能得到记录并更新它。 To make things easy, I have created a function that does the update and run transaction for you. 为了简单起见,我创建了一个为您执行更新和运行事务的函数。

The Solution 解决方案

Here is an example : 这是一个例子:

     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 takes a dynamic value (value of the field you want to update) as input and gives the {} value that you will update in the record. validationFunction需要一个动态值(您想更新字段的值)作为输入,并给出了{}值,您将在记录更新。 For example, if I want to update a field myfield if it is say true , then I will create a function updateMyField as follows 例如,如果我想更新字段myfield如果它是true ,那么我将创建一个函数updateMyField ,如下所示

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

Then this function is passed to validationFunction . 然后将此函数传递给validationFunction Why is it designed like this ? 为什么这样设计? As you have seen, we are trying to get the record after a while and then update it. 如您所见,我们试图在一段时间后获取记录然后更新它。 What if the record has been updated by someone else in between ? 如果记录已经被其他人更新了怎么办? In that case, we have to validate the data we get when the record is available for us, to prevent any incorrect updates. 在这种情况下,我们必须验证记录可用时获得的数据,以防止任何不正确的更新。 validationFunction helps us do that. validationFunction帮助我们做到这一点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM