1

I currently have a method getReviewsLength() which will get the length of the reviews from firestore for each of the item in _favourites list. However, before the lengths are done adding into reviewsLength list, the method already triggers loadingComplete() method. Is there a way to make sure getReviewsLength() method finishes before triggering loadingComplete()?

I have try with async/await but I cant seem to make it work as i am unsure of where to put there.

getReviewsLength() {
    _favourites.forEach((shopname)  {
      firestore.collection('shops').doc(shopname['shopName']).collection('reviews').get()
          .then((value) {
          setState(() {
            int length = value.size;
            reviewsLength.add(length);
          });
      });
    });
    loadingComplete();
  }

  loadingComplete(){
    setState(() {
      loading = false;
    });
    print(reviewsLength);
  }
2
  • getReviewsLength() needs to be async. You need to remove the forEach and use a regular loop, then await each call to the firestore.collection(...) Commented Dec 14, 2020 at 16:03
  • thank you @smac89. for loop works! Commented Dec 14, 2020 at 16:12

3 Answers 3

1

as mentioned by @smac89, i changed to a for loop and it works.

Future<void> getReviewsLength() async {
    for (var shopname in _favourites) {
      dynamic snapshot = await firestore.collection('shops').doc(shopname['shopName']).collection('reviews').get();
          setState(() {
            int length = snapshot.size;//value.size;
            reviewsLength.add(length);

          });
    }
    loadingComplete();
    return;
  }

  void loadingComplete(){
    setState(() {
      loading = false;
    });
    print(reviewsLength);
  }
Sign up to request clarification or add additional context in comments.

Comments

0

await lets you control the execution order and suits your specific scenario:

Future<void> getReviewsLength() async {
    Future.forEach(_favourites, (shopname) async {
         dynamic value = await firestore.collection('shops').doc(shopname['shopName']).collection('reviews').get();
          setState(() {
            int length = value.size;
            reviewsLength.add(length);
          });
    });
    loadingComplete();
    return;
}

void loadingComplete() {
 setState(() {
   loading = false;
 });
 print(reviewsLength);
}

4 Comments

forEach doesn't work with async the way you are thinking. OP needs to use regular for-loop
Hello, thanks for your help. however, it still prints an empty List. I/flutter (13575): []
Code has been corrected to address the issue you've kindly outlined
as mentioned by @smac89, for loop works ! thanks !
0

Yes making you asynchronous will help here

to make a function asynchronous you need to use the keyword async between () and {} in a function and use await keyword in the place where you running the code

getReviewsLength() async {
    _favourites.forEach((shopname)  {
      await firestore.collection('shops').doc(shopname['shopName']).collection('reviews').get()
          .then((value) {
          setState(() {
            int length = value.size;
            reviewsLength.add(length);
          });
      });
    });
    loadingComplete();
  }

  loadingComplete(){
    setState(() {
      loading = false;
    });
    print(reviewsLength);
  }

I don't know whether the above code works or not as I am not sure about firestore but a basic example would be

function() async {
    await print('hello');
    print('world');
}

here the app won't print world until it prints hello, obviously there is no use of asynchronous function here but in the case of an API request it can used and in your case too.

So what you need to do is use the await keyword in right place where it makes request or adds it to reviewsLength

Regards,

Roshan

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.