I build a repository to get data from firestore and return it as a list of objects called Keekzs
.
The required aim is to have a Future<KtList<Keekz>>
returned, however I am stuck at the point that for whatever reason I am always getting Future<KtList<Future<Keekz>>>
to be returned.
I isolated most of the inner parts and prefix it with an await expression wherever possible, but nothing changes.
Does anyone have an idea?
Here is my code:
final keekzs = await FirebaseFirestore.instance.collection(Paths.keekzsToplevelCollection).get().then(
(keekzsSnap) async => keekzsSnap.docs.map((keekzDoc) async {
final keekzDocData = keekzDoc.data();
final cardData = await keekzDoc.reference
.collection(Paths.keekzCardsSublevelcollection)
.get()
.then(
(snapshotCards) async => snapshotCards.docs,
);
keekzDocData.addAll({
"keekzCards": Map.fromEntries(
cardData.map(
(cardDataDoc) => MapEntry(cardDataDoc.id, cardDataDoc.data()),
),
)
});
return keekzDocData;
}).map((keekzMapFuture) async {
final keekzDTO = await keekzMapFuture.then(
(keekzMap) => KeekzDto.fromFirestoreData(
keekzMap,
keekzMap['keekzId'].toString(),
).toDomain(),
);
return keekzDTO;
}).toImmutableList(),
);
return keekzs;
Like @jamesdlin mentioned in the comment :
Calling
.map()
with anasync
callback will return anIterable
ofFutures
. You can useFuture.wait
to obtain aList<T>
from anIterable<Future<T>>
.
If you observe your map
function returning Future<Keekz>
instead of Keekz
because you are awaiting your result and that leads to Future<List<Future<Keekz>>>
instead of the desired Future<List<Keekz>>
.
Instead of async await
you can use Future.wait
to await all the futures returned by the map
function and then convert the resulting list of Keekz
objects into an immutable list with the help of toImmutableList()
The updated code may look something like :
final keekzsSnap = await FirebaseFirestore.instance
.collection(Paths.keekzsToplevelCollection)
.get();
final keekzFutures = keekzsSnap.docs.map((keekzDoc) async {
final keekzDocData = keekzDoc.data();
final cardDataSnap = await keekzDoc.reference
.collection(Paths.keekzCardsSublevelcollection)
.get();
final cardData = cardDataSnap.docs;
keekzDocData.addAll({
"keekzCards": Map.fromEntries(
cardData.map(
(cardDataDoc) => MapEntry(cardDataDoc.id, cardDataDoc.data()),
),
),
});
return keekzDocData;
});
final keekzDTOFutures = await Future.wait(keekzFutures);
final keekzs = keekzDTOFutures.map((keekzMap) =>
KeekzDto.fromFirestoreData(
keekzMap,
keekzMap['keekzId'].toString(),
).toDomain()).toImmutableList();
return keekzs;
Here I have separated the fetching of keekzsSnap
and mapping logic to get simplicity. By using Future.wait()
we have awaited all the futures returned by mapping logic and stored in the keekzDTOFutures
variable.
Finally, we map over keekzDTOFutures
to convert each keekzMap
into a Keekz
object, and convert the resulting list into an immutable list using toImmutableList()
.
Reference : wait static method