如何在 Dart/Flutter 中使用 Timer 和 await 一起?

How to use Timer and await together in Dart/Flutter?

提问人:An Tran 提问时间:8/2/2022 更新时间:8/2/2022 访问量:1849

问:

我有如下代码:

Timer(Duration(seconds: 5),(){
   print("This is printed after 5 seconds.");
});
print("This is printed when Timer ends");

在这种情况下,如何使用“await”?我希望当计时器结束时,然后在计时器下方运行下一个代码。我使用了 Future.delayed(),它可以做到这一点,但我不能像在 Timer() 中那样跳过 Future.delayed() 中的延迟时间。因为如果条件为真,我想跳过延迟时间。因为如果条件为真,我想跳过延迟时间。如果我使用 Future.delayed(),它没有像 Timer() 那样的 cancel() 方法。 请告诉我解决方案。谢谢

Flutter Dart 异步

评论


答:

3赞 Harsh Sureja 8/2/2022 #1

尝试 Future.delayed 而不是 Timer

await Future.delayed(Duration(seconds: 5),(){

                print("This is printed after 5 seconds.");
              });

              print('This is printed when Timer ends');

评论

1赞 An Tran 8/2/2022
我知道这种方式,但是如果条件为真,我不能跳过Future.delayed中的延迟时间。
2赞 Renik Shiroya 8/2/2022
您可以根据自己的情况给予延迟时间。例如,如果条件为 true,则延迟时间为 0,如果条件为 false,则延迟时间为 5 秒
2赞 Kaushik Chandru 8/2/2022 #2
Timer(Duration(seconds: 5),(){
   print("This is printed after 5 seconds.");
   printWhenTimerEnds();
});

void printWhenTimerEnds(){
 print("This is printed when Timer ends");
}

当您希望跳过计时器时,只需调用计时器 cancel 和 printWhenTimerEnds() 方法

2赞 ChessMax 8/2/2022 #3

有几种方法可以满足您的需求。您可以使用 Completer 并像这样:Future.any

import 'dart:async';

Completer<void> cancelable = Completer<void>();

// auxiliary function for convenience and better code reading
void cancel() => cancelable.complete();

Future.any(<Future<dynamic>>[
  cancelable.future,
  Future.delayed(Duration(seconds: 5)),
]).then((_) {
  if (cancelable.isCompleted) {
    print('This is print when timer has been canceled.');
  } else {
    print('This is printed after 5 seconds.');
  }
});

// line to test cancel, comment to test timer completion
Future.delayed(Duration(seconds: 1)).then((_) => cancel());

基本上,我们正在创造两个期货,一个是延迟的,另一个是可取消的期货。我们正在等待第一个使用 .Future.any

另一个选项是使用 CancelableOperationCancelableCompleter

例如:

import 'dart:async';
import 'package:async/async.dart';

Future.delayed(Duration(seconds: 1)).then((_) => cancel());

var cancelableDelay = CancelableOperation.fromFuture(
  Future.delayed(Duration(seconds: 5)),
  onCancel: () => print('This is print when timer has been canceled.'),
);

// line to test cancel, comment to test timer completion
Future.delayed(Duration(seconds: 1)).then((_) => cancelableDelay.cancel());

cancelableDelay.value.whenComplete(() {
  print('This is printed after 5 seconds.');
});

在这里,我们所做的几乎与上面相同,但已经可用的类。我们正在包装,因此我们现在能够取消该操作(在我们的例子中)。Future.delayedCancelableOperationFuture.delayed

另一种方式,你可以用等等来包装未来。TimerCompleter

0赞 oxore 12/21/2023 #4

您可以将 Timer 与 Completer 结合使用,以从计时器完成它,如下所示:awaitCompleter.future

final completer = Completer<bool>();
final timer = Timer(Duration(seconds: 5),(){
  print("This is printed after 5 seconds.");
  if (!completer.isCompleted) {
    completer.complete(false);
  }
});
final result = await completer.future;
print("This is printed when Timer ends");
print('Is it canceled? $result');

然后,您可以在其他位置异步取消计时器,如下所示:

timer.cancel();
if (!completer.isCompleted) {
  completer.complete(true);
}

请确保不要多次调用,否则将引发“错误状态:未来已完成”异常。completer.complete()