Reputation: 1164
I have this function that creates a list of users from their ids. A query is made for each id to get the information from Firebase RTDB.
static List<FrediUser> formattedParticipantListFromIDs(List<String> participantIDs) {
List<FrediUser> formattedParticipants = [];
for (String id in participantIDs) {
dbQuery(2, 'users', id).once().then((value) {
formattedParticipants.add(FrediUser.fromMap(value.snapshot.value as Map));
});
}
print(formattedParticipants.length);
Future.delayed(const Duration(seconds: 3), () {
print(formattedParticipants.length);
});
return formattedParticipants; }
Output of 1st print statement
0
Output of 2nd print statement
3
The return is always an empty list. As you can see, the loop and the return statement do not wait for the list to be populated. BUT, if you wait 3 seconds, the list did get populated, but it is too late.
How can I wait, in each iteration of the for loop, for the query to be done AND the .then to be called and completed?
*This method is called in a factory constructor function of a class, therefore futures and awaits cannot be used.
Upvotes: 0
Views: 338
Reputation: 599031
You'll want to use await
to wait for the asynchronous once()
method.
// 👇
static Future<List<FrediUser>> formattedParticipantListFromIDs(List<String> participantIDs)
async {
// 👆
List<FrediUser> formattedParticipants = [];
for (String id in participantIDs) {
// 👇
var value = await dbQuery(2, 'users', id).once();
formattedParticipants.add(FrediUser.fromMap(value.snapshot.value as Map));
}
print(formattedParticipants.length);
return formattedParticipants;
}
As you'll see, this means that your formattedParticipantListFromIDs
function has to be marked as async
, and returns a Future
. There is no way to prevent this, as there's no way to make asynchronous code behave synchronously.
For more on this, I recommend taking the Dart codelab on Asynchronous programming: futures, async, await
Upvotes: 1