0
votes

I have an asynchronous function in Flutter which communicates with Firestore. There's a server-function that runs, and my indication of the completion of the task a flag that I listen to using StreamSubscription. The StreamSubscription listening code is wrapped with a Future async function, yet I can't understand how do I return a Future from the function handler of StreamSubscription.

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

}

The function should wait for the stream to get a done=true future answer.

1

1 Answers

7
votes

You may use Completer in these situations:

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;
}

However, I see that you may have mixed up some concepts here.

  1. The name of your function indicates that it is dealing with a Stream, however you are returning a Future. You should not be using both Stream and Future concepts in the same function. It is somewhat confusing.

  2. You are passing the callback func, but those are not meant to be used when you are already returning a Future, since you can call func when the Future resolves.

I would rewrite this function like this:

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"];
}

And the caller:

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);