Dart cannot break out of loop while inside awaited then callback

Viewed 478

I'm trying to generate random int and check if the integer is exists in Firebase database, and do this infinitly until the integer is not exist inside database.

Below my code:

while (true) {
  _changeRandomInt()
  firebaseFirestore.collection("myCollection").doc(_randomInt).get().then((DocumentSnapshot documentSnapshot) {
  if (getFromFirebase(documentSnapshot) == null) {
    break;
  }
  });
}

But I cannot even run this code. Error: A break statement can't be used outside of a loop or switch statement. Try removing the break statement. I have my break inside while loop, then why I'm getting this error? How to fix this?

4 Answers

A break statement can't be used outside of a loop or switch statement. Try removing the break statement.

This is self explanatory. You can't use break outside of a loop. Which in your case is inside a future.

Do something like this:

_changeRandomInt();
firebaseFirestore.collection("myCollection").doc(_randomInt).get()
    .then((DocumentSnapshot documentSnapshot) {

    while (getFromFirebase(documentSnapshot) != null){
        //the body of this loop will only execute as long as the value isn't null
        //will break out of the loop as soon as the value is null
    }
}

The break you have used is inside then(), which means no loop is available immediately above `break. You can refactor your code in this manner to get it working.

while (true) {
  _changeRandomInt()
  final documentSnapshot = await firebaseFirestore.collection("myCollection").doc(_randomInt).get();
  if (getFromFirebase(documentSnapshot) == null) {
    break;
  }
}

If getFromFirebase is also a future, then await that as well inside if block.

You want to do something like this:

void functionName() async {
  try{
    var ans;
    while(getFromFirebae(ans)== null){
     ans = await firebaseFirestore.collection("myCollection").doc(_randomInt).get();
    
    }
  } catch(e){
    //error
  }
}

However, this is not the correct way. A good practice is to create a loading widget, that would show an animation while the future is loading. An even better way - to load everything in the background without stalling the overall app.

Some people have been saying that you're using "break inside a Future", but that's not quite right. Your problem is that you're using break inside of a separate function body. This is equivalent to writing:

void f() {
  break;
}

which doesn't make sense since break is not used directly within a local loop or switch statement. It doesn't matter that you're creating your function within a loop; break and continue statements perform local control flow (within a function), not across functions.

In general, instead of using Future.then, you should prefer using async/await which will have the compiler generate the callback function with appropriate code transformations for you:

while (true) {
  _changeRandomInt()

  var documentSnapshot =
    await firebaseFirestore.collection("myCollection").doc(_randomInt).get();
  if (getFromFirebase(documentSnapshot) == null) {
    break;
  }
}

Note that performing an asynchronous operation continuously in a loop isn't very efficient, so you probably should consider alternative approaches if possible, however.

Related