我正在使用Flutter框架开发一个应用程序。
期间,我遇到了Dart中的async
和async*
关键字。
有人能告诉我它们之间的区别吗?
async
关键字会给你一个 Future
async*
关键字会给你一个 Stream
。你可以在某个需要执行一些可能需要花费很长时间的工作的函数前加上 async
关键字。它会返回被包装在 Future
中的结果。
Future<int> doSomeLongTask() async {
await Future.delayed(const Duration(seconds: 1));
return 42;
}
你可以通过等待Future来获取那个结果:
main() async {
int result = await doSomeLongTask();
print(result); // prints '42' after waiting 1 second
}
您可以添加async*
关键字来创建一个返回一系列未来值的函数。结果将被包装在一个Stream中。
Stream<int> countForOneMinute() async* {
for (int i = 1; i <= 60; i++) {
await Future.delayed(const Duration(seconds: 1));
yield i;
}
}
yield
来返回值,而不是return
,因为你没有离开函数。await for
等待Stream发出的每个值。main() async {
await for (int i in countForOneMinute()) {
print(i); // prints 1 to 60, one integer per second
}
}
观看这些视频以了解更多信息,特别是生成器的视频:
async*
函数中返回一个值,只能使用yield来产生值。但是,你可以调用return;
(没有返回值)来提前退出该函数。 - Suragch将函数标记为async
或async*
,允许其使用Future
的async
/await
。
两者之间的区别是,async*
将始终返回一个Stream
,并通过yield
关键字提供一些语法糖来发出值。
因此,我们可以执行以下操作:
Stream<int> foo() async* {
for (int i = 0; i < 42; i++) {
await Future.delayed(const Duration(seconds: 1));
yield i;
}
}
这个函数每秒钟会发出一个值,并且每次都会增加。
本答案包含简化和易于理解的例子
异步
异步计算无法在启动时立即提供结果,因为程序可能需要等待外部响应,例如:
异步计算不会阻止所有计算直到结果可用,而是立即返回一个Future对象,该对象最终将“完成”并得到结果。
示例(此类型的异步调用仅可在没有返回响应的情况下使用):
void main() async {
// The next line awaits 5 seconds
await Future.delayed(Duration(seconds: 5));
// Pseudo API call that takes some time
await fetchStocks();
}
Future
Future代表一个不能立即完成的计算。普通函数返回结果,而异步函数返回Future,该Future最终将包含结果。Future会告诉您何时准备好结果。
Stream
相对)例如:
Future<String> fetchUserOrder() =>
// Imagine that this function is more complex and slow.
Future.delayed(
const Duration(seconds: 2),
() => 'Large Latte',
);
void main(List<String> arguments) async {
var order = await fetchUserOrder();
// App awaits 2 seconds
print('Your $order is ready');
}
Stream
Stream是一种异步数据事件源,提供了接收事件序列的方式。每个事件都可以是数据事件,也称为流中的元素。
async*
(streams)async*
是一个异步生成器,它返回一个Stream对象,用于创建流。
使用流和async*
的示例:
// Creating a new stream with async*
// Each iteration, this stream yields a number
Stream<int> createNumberStream(int number) async* {
for (int i = 1; i <= number; i++) {
yield i;
}
}
void main(List<String> arguments) {
// Calling the stream generation
var stream = createNumberStream(5);
// Listening to Stream yielding each number
stream.listen((s) => print(s));
}
结果:
1
2
3
4
5
如果您已经有一个流,您可以基于原始流的事件将其转换为新流。
示例(与之前相同的代码但稍有不同):
Stream<int> createNumberStream(int number) async* {
for (int i = 1; i <= number; i++) {
yield i;
}
}
// This part is taking a previous stream through itself and outputs updated values
// This code multiplies each number from the stream
Stream<int> createNumberDoubling(Stream<int> chunk) async* {
await for (final number in chunk) {
yield number*2;
}
}
void main(List<String> arguments) {
// Here we are Transforming the first stream through createNumberDoubling stream generator
var stream = createNumberDoubling(createNumberStream(5));
stream.listen((s) => print(s));
}
结果:
2
4
6
8
10
async
和 async*
是密切相关的,它们甚至来自同一个库 dart:async
。
async
表示一个 Future
和一次性交换,而 async*
则表示一个 Stream
,即多个事件的流。
异步函数在遇到await关键字之前是同步执行的。因此,异步函数体内的所有同步代码都会立即执行。
Future<int> foo() async {
await Future.delayed(Duration(seconds: 1));
return 0;
}
Async*被用来创建一个函数,它可以逐个返回一组未来的值。每个结果都被包装在流(Stream)中。
Stream<int> foo() async* {
for (var i = 0; i < 10; i++) {
await Future.delayed(Duration(seconds: 1));
yield i;
}
}
async* 会始终返回一个 Stream
Stream<int> mainStream(int value) async* {
for (int i = 1; i <= value; i++) {
yield i;
}
}
async将结果包装在Future中返回,因此可能需要更长的时间。请参考下面的示例:
void main() async {
// The next line awaits 10 seconds
await Future.delayed(Duration(seconds: 10));
}