繁体   English   中英

可以在 dart 中异步地将值插入 stream 中吗?

[英]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。

流应该在开始工作之前等待订阅者被认为是最佳实践。 这是通过使用StreamControlleronListen回调来实现的。

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 旨在迭代地监听值,而不是“一次所有项目”。 对于“所有项目一次”,您应该使用Futurereturn值,而不是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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM