In Dart,
和
有什么区别?Future<void> doStuff() async { ...
和
void doStuff() async { ...
我知道什么是未来
注意这两个函数都使用async。问题不是"异步和非异步函数之间有什么区别?"或者"你能简单解释一下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 async版本。那么区别是什么呢?
经过你的编辑,你的问题更有意义了。你的问题确实是关于原则和实践的。
原则上,返回void
的函数与返回Future<void>
的函数是不同的。一个在概念上表示不返回任何东西,另一个表示完成后可以触发回调的异步计算。
原则上,你不应该尝试使用void
函数返回的值。这说不通啊。如果您对执行await nonFutureVoid();
的代码运行Dart分析器,如果启用了await_only_futures
lint,您将得到一个警告。
在实践中,有的情况下,试图使用void
返回值碰巧不生成错误。这些都是语言中的怪癖(或实现中的bug);你不应该依赖他们. (Dart最初没有void
返回类型。当它后来被添加时,它并没有被实现为"无值"。而是表示"一个不允许使用的值"。参见第二部分:void
的遗产。一般来说,这种细微的差别并不重要。
能够做await nonFutureVoid();
是一个bug1,似乎这个bug现在已经修复了:await nonFutureVoid();
是一个错误,如果您使用Dart 2.12或更高版本,并启用null安全和更严格的类型检查。
你可以通过切换"Null Safety"来观察DartPad的新旧行为。按钮:https://dartpad.dartlang.org/b0dae0d5a50e302d26d93f2db3fa6207
1在GitHub上有很多问题,有很多来回的讨论,所以是的,它相当令人困惑。然而,大多数人似乎都同意允许await void
是不可取的。
void
函数表示该函数不返回任何内容,这意味着您不能对该函数的结果进行操作(并且不能对其结果进行await
操作)。
同时,Future<void>
函数返回一个Future对象(值为void
)。如果没有return
语句,则会显示missing_return
警告(它仍然可以编译)。您仍然可以通过等待来处理该结果,但不能实际使用该值,因为它是void
。
虽然看起来无论你使用什么都很好,但我认为为了类型安全和更好的维护,最好对每个async
函数使用Future
。