Dart Future.wait 用于多个期货并返回不同类型的结果
Dart Future.wait for multiple futures and get back results of different types
我正在使用 Flutter 从服务器下载 3 组不同的数据,然后对所有 3 组数据进行处理。我可以这样做:
List<Foo> foos = await downloader.getFoos();
List<Bar> bars = await downloader.getBars();
List<FooBars> foobars = await downloader.getFooBars();
processData(foos, bars, foobars);
但我更愿意并行下载所有 3 个数据集。我看到 Dart 有这个 Future.wait method:
Future<List<T>> wait <T>(
Iterable<Future<T>> futures, {
bool eagerError: false,
void cleanUp(
T successValue
)
})
不过看起来这只会 return 相同类型 (T) 的值。我有 3 种不同的类型,所以我不知道如何使用它来取回我的 3 个数据集。
实现此目标的最佳替代方法是什么?
谢谢!
我认为不可能做到超级漂亮的时尚。你所能做的就是这样:
void main() async {
List<List<dynamic>> result = await Future.wait<List<dynamic>>([
getStringData(),
getIntData(),
]);
print(result[0]);
print(result[1]);
}
Future<List<String>> getStringData() {
return Future.value(["a", "b"]);
}
Future<List<int>> getIntData() {
return Future.value([1, 2]);
}
嗯,类型 T 是泛型类型
您了解自己的类型,因此可以使用它们。
如果您使用的是 FutureBuilder
,您可以使用它访问不同的结果。 (与您将它们放入 Future.wait
方法的顺序相同)
snapshot.data[0] // maybe type List<Foo>
snapshot.data[1] // maybe type List<Bar>
snapshot.data[2] // maybe type String
您需要使每个 Future<T>
适应 Future
的常见类型。你可以使用 Future<void>
:
List<Foo> foos;
List<Bar> bars;
List<FooBars> foobars;
await Future.wait<void>([
downloader.getFoos().then((result) => foos = result),
downloader.getBars().then((result) => bars = result),
downloader.getFooBars().then((result) => foobars = result),
]);
processData(foos, bars, foobars);
或者如果您更喜欢 await
而不是 .then()
,则 Future.wait
调用可以是:
await Future.wait<void>([
(() async => foos = await downloader.getFoos())(),
(() async => bars = await downloader.getBars())(),
(() async => foobars = await downloader.getFooBars())(),
]);
我认为正确答案是使用官方 async 包和 FutureGroup
:
void main() {
Future<String> future1 = getData(2);
Future<String> future2 = getData(4);
Future<String> future3 = getData(6);
FutureGroup futureGroup = FutureGroup();
futureGroup.add(future1);
futureGroup.add(future2);
futureGroup.add(future3);
futureGroup.close();
futureGroup.future.then((value) => {print(value)});
}
Future<String> getData(int duration) async {
await Future.delayed(Duration(seconds: duration)); //Mock delay
return "This a test data";
}
我制作了一个辅助函数,它利用了其他答案中的一些逻辑。它使用 tuple
包,但您可以很容易地自己编写它(包含在下面)。
// Put this in future_utils.dart
/// Represents a 2-tuple, or pair.
class Tuple2<T1, T2> {
/// Returns the first item of the tuple
final T1 item1;
/// Returns the second item of the tuple
final T2 item2;
/// Creates a new tuple value with the specified items.
const Tuple2(this.item1, this.item2);
}
Future<Tuple2<T1, T2>> await2<T1, T2>(
Future<T1> Function() firstFuture,
Future<T2> Function() secondFuture) async {
late T1 item1;
late T2 item2;
await Future.wait<void>([
(() async => item1 = await firstFuture())(),
(() async => item2 = await secondFuture())(),
]);
return Tuple2(item1, item2);
}
然后调用它:
Future<List<Foo>> foos = downloader.getFoos;
Future<List<Bar>> bars = downloader.getBars;
// Will run in parallel
Tuple2<List<Foo>, List<Bar>> results = await await2(foos, bars);
// Do stuff with the results since both are complete
print(results.item1[0]);
print(results.item2[0]);
现在,如果您想要一个用于 3 个参数、4 个或更多参数,您只需复制并粘贴即可(await3
、await4
)。这不是 太 疯狂的模式,我已经将它用于 以及我链接的元组库。
我正在使用 Flutter 从服务器下载 3 组不同的数据,然后对所有 3 组数据进行处理。我可以这样做:
List<Foo> foos = await downloader.getFoos();
List<Bar> bars = await downloader.getBars();
List<FooBars> foobars = await downloader.getFooBars();
processData(foos, bars, foobars);
但我更愿意并行下载所有 3 个数据集。我看到 Dart 有这个 Future.wait method:
Future<List<T>> wait <T>(
Iterable<Future<T>> futures, {
bool eagerError: false,
void cleanUp(
T successValue
)
})
不过看起来这只会 return 相同类型 (T) 的值。我有 3 种不同的类型,所以我不知道如何使用它来取回我的 3 个数据集。
实现此目标的最佳替代方法是什么?
谢谢!
我认为不可能做到超级漂亮的时尚。你所能做的就是这样:
void main() async {
List<List<dynamic>> result = await Future.wait<List<dynamic>>([
getStringData(),
getIntData(),
]);
print(result[0]);
print(result[1]);
}
Future<List<String>> getStringData() {
return Future.value(["a", "b"]);
}
Future<List<int>> getIntData() {
return Future.value([1, 2]);
}
嗯,类型 T 是泛型类型
您了解自己的类型,因此可以使用它们。
如果您使用的是 FutureBuilder
,您可以使用它访问不同的结果。 (与您将它们放入 Future.wait
方法的顺序相同)
snapshot.data[0] // maybe type List<Foo>
snapshot.data[1] // maybe type List<Bar>
snapshot.data[2] // maybe type String
您需要使每个 Future<T>
适应 Future
的常见类型。你可以使用 Future<void>
:
List<Foo> foos;
List<Bar> bars;
List<FooBars> foobars;
await Future.wait<void>([
downloader.getFoos().then((result) => foos = result),
downloader.getBars().then((result) => bars = result),
downloader.getFooBars().then((result) => foobars = result),
]);
processData(foos, bars, foobars);
或者如果您更喜欢 await
而不是 .then()
,则 Future.wait
调用可以是:
await Future.wait<void>([
(() async => foos = await downloader.getFoos())(),
(() async => bars = await downloader.getBars())(),
(() async => foobars = await downloader.getFooBars())(),
]);
我认为正确答案是使用官方 async 包和 FutureGroup
:
void main() {
Future<String> future1 = getData(2);
Future<String> future2 = getData(4);
Future<String> future3 = getData(6);
FutureGroup futureGroup = FutureGroup();
futureGroup.add(future1);
futureGroup.add(future2);
futureGroup.add(future3);
futureGroup.close();
futureGroup.future.then((value) => {print(value)});
}
Future<String> getData(int duration) async {
await Future.delayed(Duration(seconds: duration)); //Mock delay
return "This a test data";
}
我制作了一个辅助函数,它利用了其他答案中的一些逻辑。它使用 tuple
包,但您可以很容易地自己编写它(包含在下面)。
// Put this in future_utils.dart
/// Represents a 2-tuple, or pair.
class Tuple2<T1, T2> {
/// Returns the first item of the tuple
final T1 item1;
/// Returns the second item of the tuple
final T2 item2;
/// Creates a new tuple value with the specified items.
const Tuple2(this.item1, this.item2);
}
Future<Tuple2<T1, T2>> await2<T1, T2>(
Future<T1> Function() firstFuture,
Future<T2> Function() secondFuture) async {
late T1 item1;
late T2 item2;
await Future.wait<void>([
(() async => item1 = await firstFuture())(),
(() async => item2 = await secondFuture())(),
]);
return Tuple2(item1, item2);
}
然后调用它:
Future<List<Foo>> foos = downloader.getFoos;
Future<List<Bar>> bars = downloader.getBars;
// Will run in parallel
Tuple2<List<Foo>, List<Bar>> results = await await2(foos, bars);
// Do stuff with the results since both are complete
print(results.item1[0]);
print(results.item2[0]);
现在,如果您想要一个用于 3 个参数、4 个或更多参数,您只需复制并粘贴即可(await3
、await4
)。这不是 太 疯狂的模式,我已经将它用于