Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/dart/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Flutter 取消未来超时的优雅方式_Flutter_Dart - Fatal编程技术网

Flutter 取消未来超时的优雅方式

Flutter 取消未来超时的优雅方式,flutter,dart,Flutter,Dart,在这些场景中,我需要尝试一段时间或多次,但时间不会太长。未来的.timeout属性看起来是一个自然选择。我所了解到的是,即使在超时后,最初的未来仍在继续,例如: Future<void> trySomething() async { while (true) { print('trying something...'); bool successful = false; // exit if done if (successful) {

在这些场景中,我需要尝试一段时间或多次,但时间不会太长。未来的.timeout属性看起来是一个自然选择。我所了解到的是,即使在超时后,最初的未来仍在继续,例如:

  Future<void> trySomething() async {
    while (true) {
      print('trying something...');
      bool successful = false; // exit if done
      if (successful) {
        return;
      }
      await Future.delayed(const Duration(seconds: 1));
    }
  }

  trySomething().timeout(const Duration(seconds: 10), onTimeout: () {
    print('try something else...');
  });


我不太优雅的解决方法是使用外部标志变量向主未来内的流程指示不再需要其服务:

  bool youAreTooLate = false;
  Future<void> trySomething() async {
    while (true) {
      if (youAreTooLate) {
        return;
      }
      print('trying something...');
      bool successful = false; // exit if done
      if (successful) {
        return;
      }
      await Future.delayed(const Duration(seconds: 1));
    }
  }


  trySomething().timeout(const Duration(seconds: 10), onTimeout: () {
    youAreTooLate = true;
    print('try something else...');
  });

有没有更好的方法来处理这种情况?

如果你只是想延迟重复做某件事,你可以使用计时器来实现这一点,同时保持取消它的能力

最终计时器=计时器。周期常数持续时间秒:1,t{ //在这里重复工作。 如果你应该取消{ //这是“计时器”对象。 t、 取消; } }; Future.delayedconst Durationseconds:10.then=>timer.cancel; 如果您希望在重试之前真正等待计时器内的工作完成,可以执行以下操作:

定时器; 道工异步{ //在这里做你的工作。 // ... 如果重试{ 计时器=Timerconst持续时间秒:1,工作时间; } } Future.delayedconst Durationseconds:10.then=>timer?.cancel;
这应该是可行的,但如果你已经有了一个未完成的未来,那么就没有办法真正取消它。

可能不会更优雅,但你可以将一个补全符返回给你的调用者,并在超时时完成它

Completer<void> trySomethingWithCompleter() {
  final completer = Completer<void>();
  trySomething(completer);
  return completer;
}

Future<void> trySomething(Completer<void> completer) async {
  var i = 0;
  while (true) {
    if (completer.isCompleted) {
      return;
    }
    
    bool successful = false; // exit if done
    if (successful) {
      completer.complete();
      return;
    }
    
    print('trying something... ${i++}');
    await Future.delayed(const Duration(seconds: 1));
  }
}

final completer = trySomethingWithCompleter();
completer.future.timeout(const Duration(seconds: 10), onTimeout: () {
  print('try something else...');
  completer.complete();
});

我相信这是因为你有一个永恒的真理,它永远不会打破或完成你想模仿什么?调用api并处理网络超时期间的操作?据我所知,.timeout用于等待异步函数返回值,但出现问题/时间太长,因此在.timeout中返回该值,但不会取消正在进行的函数。@Rick,下面是一个示例:有一个网络资源充当指示器。我们需要尝试阅读,直到成功,延迟1秒,但10秒后放弃。谢谢你的建议。我正在考虑,但是如果尝试时间超过计时器的时间,请求将发生冲突。我的偏好是在上一次尝试结束和下一次尝试开始之间有相等的冷却时间延迟。如果是这样,你可以使用定时器。。。并在完成尝试后创建一个新计时器。我会更新一个例子。谢谢你,本。我认为要使其工作,必须首先在doWork函数中取消计时器,因为如果实际工作时间长于计时器周期,它将触发该函数的另一个副本。此外,如果将新计时器重新分配给现有变量不会取消旧计时器,则可能需要执行此操作。此外,我们还需要对doWork进行初始调用,以使这一切顺利进行。当它工作的时候,它离我的工作环境已经不远了。
I/flutter (26426): trying something...
I/flutter (26426): trying something...
I/flutter (26426): trying something...
I/flutter (26426): trying something...
I/flutter (26426): trying something...
I/flutter (26426): trying something...
I/flutter (26426): trying something...
I/flutter (26426): trying something...
I/flutter (26426): trying something...
I/flutter (26426): try something else...
Completer<void> trySomethingWithCompleter() {
  final completer = Completer<void>();
  trySomething(completer);
  return completer;
}

Future<void> trySomething(Completer<void> completer) async {
  var i = 0;
  while (true) {
    if (completer.isCompleted) {
      return;
    }
    
    bool successful = false; // exit if done
    if (successful) {
      completer.complete();
      return;
    }
    
    print('trying something... ${i++}');
    await Future.delayed(const Duration(seconds: 1));
  }
}

final completer = trySomethingWithCompleter();
completer.future.timeout(const Duration(seconds: 10), onTimeout: () {
  print('try something else...');
  completer.complete();
});