Future<void> async 与 Dart 中的简单 void async

Future<void> async vs simply void async in Dart

在飞镖中,

说和说有什么区别

Future<void> doStuff() async { ...

void doStuff() async { ...

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

请注意,这两个函数都使用异步。问题不是 'what is the difference between async and non-async functions?' 或 'can you give a brief attempt at explaining asynchronous programming in Dart, please?'

我知道已经有一个几乎相同的问题,但是如果您仔细查看答案,您会发现实际上没有人清楚地回答了这个问题 -- 有什么区别?有什么不同吗?没有区别吗?

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

// 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');
    });
}

然后用 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');
}

记录结果:

flutter: 2021-02-23 21:46:07.436496 : delay elapsed
flutter: 2021-02-23 21:46:07.437278 : <-- executed after await statement

如您所见,它们的行为方式完全相同——等待简单的 void async 版本。那么区别是什么呢?谢谢。

A void 函数表示函数 returns 什么都没有,这意味着您不能对该函数的结果进行操作(并且不能 await 它的结果)。

同时,Future<void> 函数 returns 一个 Future 对象(其值为 void)。如果您没有 return 语句,则会出现 missing_return 警告(仍然可以编译)。您仍然可以通过等待结果来处理该结果,但不能实际使用该值,因为它是 void.

虽然看起来无论您使用什么都可以,但我认为最好为每个 async 函数使用 Future 以获得类型安全和更好的维护。

经过您的修改,您的问题更有意义了。您的问题实际上是关于原则与实践的。

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

原则上,您应该永远不要 尝试使用从void 函数中return 得到的值。这没有意义。如果您 运行 针对执行 await nonFutureVoid(); 的代码的 Dart 分析器,如果 await_only_futures lint 已启用,您将收到警告。

实际上,在 种情况下,尝试使用 void return 值恰好不会产生错误。这些是语言中的怪癖(或实现中的错误); 你不应该依赖它们。 (Dart 最初没有 void return 类型。后来添加时,它的实现不是表示“无值”,而是表示“您不允许的值”使用”。请参见 Dart 2: Legacy of the void。通常这种细微的差别应该无关紧要。)

能够做到 await nonFutureVoid();bug1,看来 那个错误现在已经修复了:如果您使用 Dart 2.12 或更高版本并启用 null-safety 和随之而来的更严格的类型检查,await nonFutureVoid(); 是一个错误。

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


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