This is my code:
List<String> databaseEntryID = <String>[];
readAllData() async {
await db.collection("users").get().then((event) {
for (var doc in event.docs) {
print(doc.id);
databaseEntryID.add(doc.id);
}
});
}
readData() {
final docRef = db.collection(databaseEntryID[0]).doc(databaseEntryID[1]);
docRef.get().then(
(res) => print("Successfully completed"),
one rror: (e) => print("Error completing: $e"),
);
}
If I call readAllData()
first and then do readData()
second, I get a RangeError: RangeError (index): Invalid value: Valid value range is empty: 0
.
I don't fully grasp how async works, so what am I doing wrong here, how do I get the list updated first, and then access the first and second String?
CodePudding user response:
For Async, I usually implement Listener Pattern. This way, when you receive data from async you can work with it. Basically what happens here is that you cann readData() before the readAllData() result arrives. What you could do/try to do to patch this is: 1.
readAllData() async {
await db.collection("users").get().then((event) {
for (var doc in event.docs) {
print(doc.id);
databaseEntryID.add(doc.id);
}
// Do here the things you might want to do when receiving an information (such as notifying the listeners..)
});
}
Or 2.
List<String> databaseEntryID = <String>[];
Boolean databaseHydrated = false;
readAllData() async {
await db.collection("users").get().then((event) {
for (var doc in event.docs) {
print(doc.id);
databaseEntryID.add(doc.id);
}
databaseHydrated = true;
});
}
readData() {
if(databaseHydrated) {
final docRef = db.collection(databaseEntryID[0]).doc(databaseEntryID[1]);
docRef.get().then(
(res) => print("Successfully completed"),
one rror: (e) => print("Error completing: $e"),
);
} else {
// Do whatever you want, like toggle a loading screen while waiting for async data ?
}
}
Hope it helps!
CodePudding user response:
I came across this after searching, should've checked this first (I usually avoid doc pages as they're made too complex like, this one is guide like): https://dart.dev/codelabs/async-await
So the simplest fix is to:
List<String> databaseEntryID = <String>[];
readAllData() async {
await db.collection("users").get().then((event) {
for (var doc in event.docs) {
print(doc.id);
databaseEntryID.add(doc.id);
}
});
}
readData() async {
await readAllData();
final docRef = db.collection(databaseEntryID[0]).doc(databaseEntryID[1]);
docRef.get().then(
(res) => print("Successfully completed"),
one rror: (e) => print("Error completing: $e"),
);
}
Call the readAllData
function from readData
using the await keyword to show that it needs to wait for its return, and then execute the readData
method (needs async modifier).