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

Posted

技术标签:

【中文标题】Future<void> async 与 Dart 中的简单 void async【英文标题】:Future<void> async vs simply void async in Dart 【发布时间】:2021-05-26 08:50:48 【问题描述】:

在 Dart 中,

和说有什么区别

Future<void> doStuff() async  ...

void doStuff() async  ...

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

请注意,这两个函数都使用异步。问题不是“异步函数和非异步函数有什么区别?”或者“您能简要介绍一下 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');
    );

然后用 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 异步版本。那么区别是什么呢?谢谢。

【问题讨论】:

我很确定这是一个与我实际回答的问题相同的问题:What's the difference between returning void vs returning Future<void>? 好吧,我不知道有这个问题,谢谢......虽然实际差异在 cmets 中被散列出来并且似乎没有定论,但这并不是最大的。 你不能等待虚空,你可以等待未来这就是区别。 @NerdyBunz 嗯?答案中解释了差异:调用者不能等待异步 void 函数完成。时期。这没有什么不确定的。 我预计评论会被删除。 :D 【参考方案1】:

void 函数表示该函数不返回任何内容,这意味着您不能对该函数的结果采取行动(也不能await 对其结果进行操作)。

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

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

【讨论】:

Future 不需要返回语句 AFAIK。区别只是一个可以等待,另一个我不能想?我实际上并没有意识到这会编译... @shawnblais 是的,目前它不是必需的,只是一个警告。你也是对的,void 函数不能等待,因为它表明它不会返回任何东西 感谢您的努力。我稍微修改了这个问题。【参考方案2】:

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

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

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

在实践中,种情况,尝试使用 void 返回值碰巧不会产生错误。这些是语言中的怪癖(或实现中的错误); 您不应依赖它们。 (Dart 最初没有void 返回类型。后来添加时,它并没有实现为“无值”,而是表示“不允许使用的值”。见@ 987654322@。通常情况下,细微的差别并不重要。)

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

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


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

【讨论】:

以上是关于Future<void> async 与 Dart 中的简单 void async的主要内容,如果未能解决你的问题,请参考以下文章

返回 void 与返回 Future<void> 有啥区别?

boost::async 只返回 void?

c++ async future get

如何将 std::future<T> 转换为 std::future<void>?

std::future, std::async, std::promise

std::future, std::async, std::promise