![](/img/trans.png)
[英]How can I asynchronously stream loaded objects from a list of futures in Dart
[英]Possible to insert values into stream asynchronously in dart?
我有一个 function 下载 RSS 提要并解析它。 之后,我遍历每个团队并对其进行一些处理。 目前,这个处理是异步的,只要它完成我就产生它,但这意味着每个项目都将被线性处理。 有没有办法一次处理所有项目并在处理时产生它们?
高级代码:
Stream<String> processRSSFeedItems() async* {
RSSFeed rssFeed = RSSFeed("some URL");
for(int itemIndex = 0; itemIndex < rssFeed.items.lengthl itemIndex++){
String processedItem = await processRssItem(rssFeed.items[itemIndex]);
yield processedItem;
}
}
void refreshRssFeed(){
var stream = processRSSFeedItems();
stream.listen((item) => setState(() => something(item));
}
有没有办法为所有项目调用 processRssItem() 而无需等待前一个过程完成并在它们到达时产生它们?
你可以做
List<Future<String>> futures = <Future<String>>[];
for(int itemIndex = 0; itemIndex < rssFeed.items.length; itemIndex++){
futures.add(processRssItem(rssFeed.items[itemIndex]));
}
// Waits for multiple futures to complete and collects their results.
final result = await Future.wait<String>(futures);
for(var i = 0 ; i < result.length; i++) {
yield result[i];
}
您可以在元素到达时将它们添加到StreamController ,并返回 stream。
流应该在开始工作之前等待订阅者被认为是最佳实践。 这是通过使用StreamController
的onListen
回调来实现的。
import 'dart:async';
...
Stream<String> processRSSFeedItems() {
late StreamController<String> controller;
void startProcessRssFeedItems() {
RSSFeed rssFeed = RSSFeed("some URL");
int workers = rssFeed.items.length;
for (int itemIndex = 0; itemIndex < rssFeed.items.length; itemIndex++) {
processRssItem(rssFeed.items[itemIndex]).then(
(processedItem) {
controller.add(processedItem);
if (--workers == 0) {
controller.close();
}
},
onError: (error) {
if (--workers == 0) {
controller.close();
}
},
);
}
}
controller = StreamController<String>(
onListen: startProcessRssFeedItems,
);
return controller.stream;
}
从你的问题:
“目前,这个处理是异步的,每当它完成时,我就产生它,但这意味着每个项目都将被线性处理。有没有办法一次处理所有项目并在处理它们时产生它们?”
在这种情况下,“yield”等同于“return”。 因此 Stream 不适合您的用例,因为 Streams 旨在迭代地监听值,而不是“一次所有项目”。 对于“所有项目一次”,您应该使用Future
并return
值,而不是yield
。 在List<Future>
上使用while
循环而不是for
循环将一个接一个地处理它们:
Future getAllWhenProcessed()async{
var items = rssFeed.items;
var count = items.length;
var results = [];
while(count > 0){
results.add(await processRssItem(items[--count]));
}
return results;
}
然后就
getAllWhenProcessed().then((value){ updateUi(); });
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.