Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flutter: Future.doWhile end timeout exception

Tags:

flutter

I have problem with dosen't stop iteration in Future.doWhile after catch timeout error.

Below is code my example function:

 Future<void> testFunction() async {
    print(">>> start test");

    int sec = 0;
    await Future.doWhile(() async {
      await Future.delayed(Duration(seconds: 5));
      sec += 5;
      if (sec >= 60) {
        print("> end doWhile after 60 seconds");
        return false;
      }
      print("> elapsed $sec seconds");
      return true;
    }).timeout(Duration(seconds: 20)).then(print).catchError(print);

    print(">>> end test");
  }

and result:

I/flutter ( 6081): >>> start test
I/flutter ( 6081): > elapsed 5 seconds
I/flutter ( 6081): > elapsed 10 seconds
I/flutter ( 6081): > elapsed 15 seconds
I/flutter ( 6081): TimeoutException after 0:00:20.000000: Future not completed
I/flutter ( 6081): >>> end test
I/flutter ( 6081): > elapsed 20 seconds
I/flutter ( 6081): > elapsed 25 seconds
I/flutter ( 6081): > elapsed 30 seconds
I/flutter ( 6081): > elapsed 35 seconds
I/flutter ( 6081): > elapsed 40 seconds
I/flutter ( 6081): > elapsed 45 seconds
I/flutter ( 6081): > elapsed 50 seconds
I/flutter ( 6081): > elapsed 55 seconds
I/flutter ( 6081): > end doWhile after 60 seconds

Why doWhile's iteration works after catch timeout error?

like image 451
Kijju Avatar asked Oct 20 '25 15:10

Kijju


1 Answers

The timeout method

Future<T> timeout (

    Duration timeLimit,
    {FutureOr<T> onTimeout(
    )}

) 

isn't meant to stop the execution of the Future it's called on. You can think of it equivalent to simply a delayed method which waits for timeLimit duration for the Future to return a value. If Future doesn't complete in timeLimit you get a chance to do some work with onTimeout so code doesn't break.

If you really want to stop execution of doWhile method in your case, you could implement it like this:

Future<void> testFunction() async {
  print(">>> start test");
  var toContinue = true;

  int sec = 0;
  await Future.doWhile(() async {
    await Future.delayed(Duration(seconds: 1));
    sec += 1;
    if (sec >= 5) {
      print("> end doWhile after 5 seconds");
      return false;
    }
    print("> elapsed $sec seconds");
    return toContinue;
  }).timeout(Duration(seconds: 3), onTimeout: () {
    toContinue = false;
    print('> Timed Out');
  });
  print(">>> end test");
}

Output:

>>> start test
> elapsed 1 seconds
> elapsed 2 seconds
> Timed Out
>>> end test
> elapsed 3 seconds

Even this author is wrong about timeout method

If you run the code about. You’ll see 0 timed out and you'll never see Delay complete for Future 0.

For further reading:
Future.timeout documention is misleading
Add possibility to truly cancel/dispose Fututre

like image 60
happy_san Avatar answered Oct 22 '25 03:10

happy_san



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!