【问题标题】:How do I asynchronously listen to a value in Firestore using an async function?如何使用异步函数异步监听 Firestore 中的值?
【发布时间】:2019-12-18 09:07:56
【问题描述】:

我在 Flutter 中有一个与 Firestore 通信的异步函数。 有一个服务器功能正在运行,并且我指示任务完成的标志是我使用 StreamSubscription 收听的标志。 StreamSubscription 监听代码用 Future 异步函数包装,但我不明白如何从 StreamSubscription 的函数处理程序返回 Future。

static Future<bool> listenToProcess(
  String doc, Function func) {

  StreamSubscription<DocumentSnapshot> stream =  Firestore.instance.collection('requests').document(doc)
      .snapshots().listen((data){
    if (data.data["done"])
      func(true);
    print ("change " + data.data["done"].toString());
  });

}

该函数应等待流获得 done=true 未来答案。

【问题讨论】:

    标签: asynchronous flutter dart google-cloud-firestore future


    【解决方案1】:

    您可以在这些情况下使用Completer

    static Future<bool> listenToProcess(String doc, Function func) {
      final completer = Completer<bool>();
      final stream = Firestore.instance
          .collection('requests').document(doc).snapshots().listen((data) {
            ...
            completer.complete(data.data["done"]);
          });
    
      return completer.future;
    }
    
    

    但是,我发现您可能在这里混淆了一些概念。

    1. 您的函数名称表明它正在处理Stream,但是您返回的是Future。您不应在同一函数中同时使用 StreamFuture 概念。这有点令人困惑。

    2. 您正在传递回调 func,但当您已经返回 Future 时,不应该使用这些回调,因为您可以在 Future 解析时调用 func

    我会这样重写这个函数:

    static Future<bool> checkIfRequestIsDone(String doc) async {
      // Retrieve only the first snapshot. There's no need to listen to it.
      DocumentSnapshot snapshot = await Firestore.instance
          .collection('requests').document(doc).snapshots().first;
    
      return snapshot["done"];
    }
    

    和调用者:

    bool isRequestDone = await checkIfRequestIsDone(doc);
    
    // Call the server-function as soon as you know if the request is done.
    // No need for callback.
    serverFunction(isRequestDone); 
    

    【讨论】:

    • 非常感谢您的详尽回答,完成者的工作就像一个魅力。但是 isRequestDone 方法不是很好,因为我需要等到答案为真。如果为 false 代码将继续执行 serverFunction(),不是吗?
    • 然后在调用serverFunction()之前检查isRequestDone是否为真:if (isRequestDone) serverFunction(true);。我真的认为您应该考虑这一点,因为正如我所解释的,您最初的实现混淆了很多概念。
    • 是的,所以我做了什么来省略 func() 代码。我看不出我怎么能简单地使用 if (isRequestDone) 因为我必须以某种方式继续检查它..我肯定不会循环检查,即使没有计时器..我认为流方法是好的,只要我在它变为true后取消它。
    • Completer 太棒了!非常感谢分享!
    猜你喜欢
    • 2011-03-30
    • 2011-12-06
    • 2020-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-09
    • 2011-07-09
    相关资源
    最近更新 更多