I am working on a fitness project, where the user takes "exercises" and can make some of them favorite. The Exercises and the Favorites by user are stored in different collections in Firebase Firestore. When I load the exercises into the app, as I load them I want to check per exercise, which have been favorited. I want to do this at the same time I load the exercises. So I have created the following code:
Future<void> fetchAndSetExercises() async {
final List<Exercise> loadedExercises = [];
final extracted = await _firestore.collection('exercises').get();
extracted.docs.forEach(
(exerciseData) async {
print("EXERCISE DATA: ${exerciseData['title']}");
// TODO: Get Favorite
final checkFav = await _firestore
.collection('favorites')
.doc('${_firebaseAuth.currentUser.uid}')
.collection('userFavorites')
.doc(exerciseData.id)
.get();
if (checkFav.exists) {
print('FOUND A RECORD');
}
loadedExercises.add(
Exercise(
id: exerciseData.id,
title: exerciseData['title'],
description: exerciseData['description'],
imageUrl: exerciseData['imageUrl'],
itemUrl: exerciseData['itemUrl'],
minutes: exerciseData['minutes'],
),
);
}, // end for each function
); // end for each
_exercises = loadedExercises.toList();
notifyListeners();
}
Here as the extracted exercises are loaded, I make another get request. So there are two different get requests in this code. When I run the code without the second firebase get, it works fine, but with the second get it gives and error:
RangeError (index): Invalid value: Valid value range is empty: 0
I haven't been able to find any solution for this. Maybe it is not possible to nest Firebase get requests to different collections?
If anyone could help clarify this or point to how I can solve this, I would really appreciate it.
Many thanks
Carson
CodePudding user response:
extracted.docs.forEach(
(exerciseData) async {
The forEach method waits for your function to finish, but your function is async
, which means it finishes immediately and returns a Future<>
that needs to be await
ed. But you do not await
. the forEach
method does not await
the results either.
So move your code using await
out from the anonymous method that is not awaited into your main body of code:
for(var exerciseData in extracted.docs) {
print("EXERCISE DATA: ${exerciseData['title']}");
// TODO: Get Favorite
final checkFav = await _firestore
.collection('favorites')
.doc('${_firebaseAuth.currentUser.uid}')
.collection('userFavorites')
.doc(exerciseData.id)
.get();
if (checkFav.exists) {
print('FOUND A RECORD');
}
loadedExercises.add(
Exercise(
id: exerciseData.id,
title: exerciseData['title'],
description: exerciseData['description'],
imageUrl: exerciseData['imageUrl'],
itemUrl: exerciseData['itemUrl'],
minutes: exerciseData['minutes'],
),
);
}