Search code examples
dartfluttergoogle-cloud-firestorefuturedart-async

Use iteration helpers like .map(), .where(), etc in an async manner?


Short: toList() executes before makeMaker causing the markers to have null objects.

Long: In Firestore, I have table and game collections and inside of table, there is a game field(type=reference). With a StreamBuilder, I can access tables. And I iterate through tables and try to fill in their game fields with real data by using get as seen in below;

if (snapshot.hasData) {
            tabledocs = snapshot.data.documents;
            markers = tabledocs
                .map((tabledoc) {
              DocumentReference gameref = tabledoc.data['game'];
              //game field is a reference type field which points to another collection
              gameref.get().then((gdoc) {
                tabledoc.data['game'] = gdoc;
                Marker marker = makeMarker(tabledoc);  //<--------Executes later
                return marker;
              });
            }).toList();                               //<--------Executes first
          }

Because gameref.get().then() takes time, the toList() at the bottom executes before each marker is generated and added in to markers.

If there are 3 markers returned from Firestore, our markers is an array of 3 null markers. I think makeMarker(..) did not execute yet most probably.

Is there a way for the map method to wait for the gets to finish and then initialize markers array with non-null values? Or can you show me another way to accomplish what I want.


Solution

  • You can either use

    await for(var tabledoc of tabledocs) { 
    
    }
    

    or if it is not necessary that the items are executed in order (the result will be in the order of the original items though)

    var markers = await Future.wait(tabledocs
      .map((tabledoc) {
        DocumentReference gameref = tabledoc.data['game'];
              //game field is a reference type field which points to another collection
        var gdoc = await gameref.get();
        tabledoc.data['game'] = gdoc;
        Marker marker = makeMarker(tabledoc);
        return marker;
      });