Recently, While I was working on the project. I have to make multiple local database calls. I used forEach Loop For that purpose.
My Code was Something like this:
void main() {
final List<int> ids = [1,5,3,7];
print("Loop Started");
ids.forEach((element)async{
await getDataAsId(element);
});
print("Loop Ended");
}
Future<void> getDataAsId(int id)async{
await Future.delayed(Duration(milliseconds:400),(){
print("${id*2}");
});
}
My Code Inside forEach was executed after all code runs, What the heck?
Why This Happened? Let's See
After a Bit of Research, the block of forEach wasn't run at last. forEach was executed at its time not later. What happened was with my Future function.
Array Methods such as forEach execute codes synchronously. That means each time Future is registered in Queue not waited. You cannot wait for Future(promises) inside of arrayMethods.
Behind the scene, it does something like this.
void main(){
final List<int> ids = [1,2,4];
print("Loop Started");
for(int element in ids){
callback();
}
print("Loop Ended");
}
void callback()async{
await myDatabase();
}
Future<void> myDatabase()async{
Future.delayed(Duration(milliseconds:500),(){
print("HI");
});
}
So, What's the Solution? Let's Discuss It.
Solutions
1# Using Basic Loops
Just use forEach, for, while or do while loop when you need to call Future which you want to wait.
void main() async{
final List<int> ids = [1,5,3,7];
print("Loop Started");
for(int element in ids){
await getDataAsId(element);
}
print("Loop Ended");
}
Future<void> getDataAsId(int id)async{
await Future.delayed(Duration(milliseconds:400),(){
print("${id*2}");
});
}
#2 Store Future and Call All At Once
For this solution, we will map all futures. And run all Future at once.
void main() async{
final List<int> ids = [1,5,3,7];
print("Loop Started");
final List<Future<void>> futures = ids.map((e)=>getDataAsId(e)).toList();
await Future.wait(futures);
print("Loop Ended");
}
Future<void> getDataAsId(int id)async{
await Future.delayed(Duration(milliseconds:400),(){
print("${id*2}");
});
}
If you are on Javascript use
await Promise.all(futures);