我正在使用颤振框架制作一个应用程序。 在此期间,我遇到了Dart中的关键字async和async*。 有人能告诉我它们之间的区别吗?
当前回答
async*将始终返回一个流
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));
}
其他回答
解决方案,起源和见解
这个答案包括简单易懂的例子
异步
异步计算不能在启动时立即提供结果,因为程序可能需要等待外部响应,例如:
读取文件 查询数据库 从API获取数据
异步计算不会阻塞所有计算直到结果可用,而是立即返回一个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 最终控制结果。未来会告诉你什么时候结果准备好了。
当async函数返回值时,将追加Future 表示单个计算的结果(与流相反)
例子:
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');
}
流
异步数据事件的源。 流提供了一种接收事件序列的方法。每个事件要么是一个数据事件,也称为流的一个元素。
流是结果的序列 从流中你会得到结果通知(流元素)
异步*(流)
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,即多个事件的流
async*将始终返回一个流
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));
}
异步函数同步执行,直到它们到达await关键字为止。因此,异步函数体中的所有同步代码都会立即执行。
Future<int> foo() async {
await Future.delayed(Duration(seconds: 1));
return 0;
}
Async*用于创建一个每次返回一堆未来值的函数。每个结果都包装在一个流中。
Stream<int> foo() async* {
for (var i = 0; i < 10; i++) {
await Future.delayed(Duration(seconds: 1));
yield i;
}
}
简短的回答
async给你一个Future async*给你一个流。
异步
将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<int> countForOneMinute() async* {
for (int i = 1; i <= 60; i++) {
await Future.delayed(const Duration(seconds: 1));
yield i;
}
}
这种功能的技术术语是异步发生器功能。你使用yield来返回一个值而不是return,因为你没有离开函数。
您可以使用await for来等待流发出的每个值。
main() async {
await for (int i in countForOneMinute()) {
print(i); // prints 1 to 60, one integer per second
}
}
发生了
观看这些视频了解更多,特别是关于生成器的视频:
隔离和事件循环 期货 流 异步/等待 发电机
将函数标记为async或async*允许它在Future中使用async/await。
两者的区别在于async*总是返回一个流,并提供一些语法糖来通过yield关键字发出一个值。
因此,我们可以做到以下几点:
Stream<int> foo() async* {
for (int i = 0; i < 42; i++) {
await Future.delayed(const Duration(seconds: 1));
yield i;
}
}
该函数每秒钟产生一个值,该值每次都增加。