据我了解,您可以在 Dart 中等待一个阻止当前执行的异步函数的未来,直到将来返回结果。
例如,调用inSequence()
需要三秒钟来打印其输出。
// Return a String after a one second delay. No surprises here.
Future<String> long() async {
await Future.delayed(Duration(seconds: 1));
return ":)";
}
void inSequence() async {
// sequentially wait on the futures - takes 3 seconds
print(await long());
print(await long());
print(await long());
}
或者,如果您想一次运行所有期货,您可以调用Future.wait([...])
。然后所有期货将执行,一旦准备好任何后续的异步调用,结果将可用,因此下面的inParallel()
只需要一秒钟即可执行。
void inParallel() async {
var f1 = long();
var f2 = long();
var f3 = long();
Future.wait([f1,f2,f3]); // wait on all futures in parallel.
print(await f1);
print(await f2);
print(await f3);
}
以上所有内容对我来说都很有意义。但是,在下面查看以confusing()
代码的行为并不像我期望的那样。我希望这个函数需要三秒钟来执行,因为在打印字符串之前等待每个await
,然后继续下一个,直到函数在三秒后完成。 实际上,此功能只需1秒钟,即可一次打印所有结果。 为什么?这是如何工作的?
void confusing() async {
var f1 = long();
var f2 = long();
var f3 = long();
print(await f1);
print(await f2);
print(await f3);
}
谢谢。
或者,如果你想一次运行所有期货,你可以调用
Future.wait([...])
。然后所有期货将执行,一旦准备好任何后续异步调用,结果将可用,因此下面的inParallel()
只需要一秒钟即可执行。
不一定。 使用Future.wait
本身不会导致操作并行执行;如果可以的话,它只是不会阻止它们并行发生。1
实际上,此功能只需1秒钟,即可一次打印所有结果。 为什么?这是如何工作的?
void confusing() async { var f1 = long(); var f2 = long(); var f3 = long(); print(await f1); print(await f2); print(await f3); }
你给long
打了三次电话。 调用long
立即开始执行其正文,该主体调用Future.delayed(Duration(seconds: 1))
。 然后,long
向调用方返回Future
。
因此,对应于f1
、f2
和f3
Future
的异步操作都已启动,因此它们都将在 1 秒后完成。 注意Future.wait
基本上做同样的事情,只是Future.wait
在Future
s 的Iterable
上运行,而不是固定数量的 s。Future.wait
没有什么根本性的魔力。
相反,当您执行以下操作时:
void inSequence() async { // sequentially wait on the futures - takes 3 seconds print(await long()); print(await long()); print(await long()); }
在上一个操作完成之前不要调用long()
(因此不要调用Future.delayed
),因此异步调用都将序列化。
1隔离中的 Dart 代码在单个线程中执行。 如果执行两个异步操作,但每个操作都在主 Dart 线程中执行其所有工作,则将它们与Future.wait
一起使用将并发执行,但不能并行执行。 例如:
Future<void> spin(Duration duration) async {
await Future.delayed(Duration.zero);
var endTime = DateTime.now().add(duration);
while (DateTime.now().isBefore(endTime)) {}
}
void main() async {
var oneSecond = const Duration(seconds: 1);
var stopwatch = Stopwatch()..start();
await Future.wait([spin(oneSecond), spin(oneSecond)]);
print(stopwatch.elapsed.inSeconds); // Prints: 2
}
在上面的代码中,spin
执行一个占用主线程 1 秒的同步循环,但来自两个调用的循环无法同时执行。
但是,这并不意味着某些异步操作不能并行发生。 在大多数情况下,异步操作最终会执行一些使用操作系统线程实现的较低级别的操作(例如在 Dart VM/运行时中)。 或者,您可能执行执行异步 I/O 的文件系统操作。 这取决于异步操作的实现。 如果要允许异步操作并行发生(如果可能),则通常应使用Future.wait
。