首页 > 解决方案 > Flutter:Future.doWhile 结束超时异常

问题描述

在捕获超时错误后,我遇到了在 Future.doWhile 中不停止迭代的问题。

下面是我的示例函数的代码:

 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");
  }

结果:

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

为什么 doWhile 的迭代在 catch 超时错误后起作用?

标签: flutter

解决方案


超时方法

Future<T> timeout (

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

) 

并不意味着停止它被调用的 Future 的执行。您可以将其视为简单的延迟方法,该方法等待timeLimit持续时间让 Future 返回一个值。如果 Future 没有在timeLimit中完成,你有机会使用onTimeout做一些工作,这样代码就不会中断。

如果您真的想在您的情况下停止执行 doWhile 方法,您可以像这样实现它:

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");
}

输出:

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

即使这个作者对超时方法也是错误的

如果你运行一下代码。您会看到 0 超时,并且您永远不会看到 Future 0 的延迟完成。

进一步阅读:
Future.timeout 文档具有误导性
添加真正取消/处置 Fututre 的可能性


推荐阅读