Dart 中的 Future<void> 异步与简单的 void 异步

Boo*_*unz 9 asynchronous future dart flutter

在达特中,

说 和 说 有什么区别

Future<void> doStuff() async { ...
Run Code Online (Sandbox Code Playgroud)

void doStuff() async { ...
Run Code Online (Sandbox Code Playgroud)

我知道 Future<T> 是什么以及 async/await 一般如何工作,但我从未意识到 Future<void> 是一件事。我有一些代码到处都有 Future<void> ,我想用我正常的做事方式替换它,但我不想破坏任何东西。

请注意,这两个函数都使用异步。问题不是“异步函数和非异步函数之间有什么区别?” 或者“您能简短地尝试解释一下 Dart 中的异步编程吗?”

我知道已经有一个几乎相同的问题,但如果你仔细观察答案,你会发现没有人真正以清晰的方式回答这个问题 - 有什么区别?有什么区别吗?有没有区别?

为了详细说明,请考虑以下两个函数:

// notice there is no warning about not returning anything
Future<void> futureVoid() async {
    await Future.delayed(Duration(seconds: 2), () {
      var time = DateTime.now().toString();
      print('$time : delay elapsed');
    });
}

void nonFutureVoid() async {
    await Future.delayed(Duration(seconds: 2), () {
      var time = DateTime.now().toString();
      print('$time : delay elapsed');
    });
}
Run Code Online (Sandbox Code Playgroud)

然后使用 onPressed() 函数为的按钮测试它们:

onPressed: () async {
    await nonFutureVoid(); // notce that this await *DOES* delay execution of the proceeding lines.
    var time = DateTime.now().toString();
    print('$time : <-- executed after await statement');
}
Run Code Online (Sandbox Code Playgroud)

日志结果:

flutter: 2021-02-23 21:46:07.436496 : delay elapsed
flutter: 2021-02-23 21:46:07.437278 : <-- executed after await statement
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,它们的行为方式完全相同——正在等待简单的 void 异步版本。那么区别是什么呢?

jam*_*lin 9

经过您的编辑,您的问题更有意义。你的问题实际上是关于原则与实践的。

原则上,返回的函数void与返回 的函数不同Future<void>。一个在概念上代表不返回任何内容的东西,另一个代表一种异步计算,可以在完成时触发回调。

原则上,您永远不应该尝试使用函数返回的值void。这没有道理。如果您针对这样做的代码运行 Dart 分析器,如果启用了lintawait nonFutureVoid();,您将收到警告。await_only_futures

实际上,在某些情况下尝试使用void返回值恰好不会生成错误。这些是语言中的怪癖(或实现中的错误);你不应该依赖他们。(Dart 最初没有void返回类型。后来添加它时,它并没有实现为表示“无值”,而是表示“不允许使用的值”。请参阅Dart 2:遗留的void。通常这种细微的差异并不重要。)

能够做到这await nonFutureVoid();一点是一个错误1 ​​,并且似乎该错误现已修复await nonFutureVoid();如果您使用 Dart 2.12 或更高版本并启用 null 安全性以及随之而来的更严格的类型检查,则这是一个错误。

您可以通过切换“Null Safety”按钮来观察 DartPad 的新旧行为:https://dartpad.dartlang.org/b0dae0d5a50e302d26d93f2db3fa6207


1 GitHub 上提交了很多问题,并进行了大量的反复讨论,所以是的,这相当令人困惑。然而,大多数人似乎都同意允许await void是不可取的。