【问题标题】:Dart - return data from a Stream Subscription blockDart - 从 Stream Subscription 块返回数据
【发布时间】:2020-08-09 16:32:01
【问题描述】:

我使用 listen 方法订阅了一个流,因此我可以在数据进入时对其进行处理。如果我找到了我要查找的内容,我想取消该流并从流订阅块中返回数据。

我有一个可行的实现,但我正在使用 Completer 来阻止函数立即返回并且感觉很混乱,所以我想知道是否有更好的方法来实现这一点。这是我的代码 sn-p:

Future<String> _extractInfo(String url) async {
    var data = <int>[];
    var client = http.Client();
    var request = http.Request('GET', Uri.parse(url));
    var response = await client.send(request);

    var process = Completer();
    var interestingData = '';

    StreamSubscription watch;

    watch = response.stream.listen((value) async {
      data.clear(); //clear the previous stale data from the list so searching can be faster
      data.addAll(value);

      if (
        hasInterestingData(data) //search the bytelist for the data I'm looking for
      ){
        interestingData = extractInterestingData(data) //extract the data if it's been found. This is what I want my function to return;
        await watch.cancel(); //cancel the stream subscription if the data has been found. ie: Cancel the download
        process.complete('done'); //complete the future, so the function can return interestingData.
      }
    });

    watch.onDone(() {
      //complete the future if the data was not found...so the function will return an empty string
      if (!process.isCompleted) {
        process.complete('done');
      }
    });

    await process.future; //blocks the sync ops below so the function doesn't return immediately
    client.close();
    return interestingData;
  }

【问题讨论】:

    标签: asynchronous dart async-await stream


    【解决方案1】:

    当您在 async 函数中时,您应该使用 await for 来处理此类事情。

      Future<String> _extractInfo(String url) async {
        var client = http.Client();
        var request = http.Request('GET', Uri.parse(url));
        var response = await client.send(request);
    
        await for (var data in response.stream) {
          if (hasInterestingData(data)) {
            return extractInterestingData(data); // Exiting loop cancels the subscription.
          }
        }
        return "done";
      }
    

    然而,虽然这种方法等同于您的代码,但它可能同样存在缺陷。 除非您正在寻找一个单字节,否则您要冒着被分割为连续数据事件的风险。你喜欢确实需要保留之前数据数组的某些部分,或者一些总结你已经看到的状态,但是多少取决于你实际寻找的内容。

    【讨论】:

    • 谢谢,我通过在找到数据后保存最后一个块的一部分和下一个块的一部分来解决这个缺陷。
    猜你喜欢
    • 1970-01-01
    • 2019-01-13
    • 1970-01-01
    • 2016-08-03
    • 1970-01-01
    • 1970-01-01
    • 2020-08-31
    • 2015-05-15
    • 1970-01-01
    相关资源
    最近更新 更多