【问题标题】:Using await for with streams and handling done + onError callbacks使用 await for 流和处理 done + onError 回调
【发布时间】:2021-12-18 07:16:55
【问题描述】:

我正在使用dart:io的HTTP客户端下载大文件,方式如下:

final url = Uri.parse(fileUrl);
final request = await httpClient.getUrl(url);
final response = await request.close();

然后我使用HttpClientResponse 类型的response 实现Stream<List<int>>,其中每个发出的List<int> 代表正在下载的文件块。

我的目标是将该流“转换”为另一个流,为此,我最近了解到await for + yield 可以做到这一点:

Stream<Event> processResponse(HttpClientResponse response) async* {
    await for (final List<int> chunk in response) {
        yield Event.FileChunk(chunk: chunk);
    }
    yield const Event.Completed();
}

最初,在了解await for之前,我打算使用Stream&lt;T&gt;.listen方法,它接受4个参数:

  1. onData 回调用于流中每个发出的值,
  2. onError 回调,用于在发出值时通知错误,
  3. 通知流的onDone 回调正在关闭并且不会发出任何新值,最后
  4. cancelOnError 自解释的布尔参数。

通过使用await for () {},我相信我涵盖了#1 和#3,因为我将获得所有发出的值,完成后,代码将离开await for 的范围,这应该意味着它已经完成。

但是错误呢?由于这些流将是冗长且繁重的 IO 流,因此肯定随时可能出现 IO 错误。他们是如何报道的?我如何访问他们的数据以报告这些数据并在需要时进行调试?

【问题讨论】:

  • 如果您想“转换”Stream,请使用 Stream.map / Stream.transform 方法,更多信息请点击此处:Methods that modify a stream
  • 谢谢!似乎map 起到了作用,因为文档说:Error and done events are passed through unchanged to the returned stream,这意味着我可以在收听转换后的流时捕捉到它们。但是,StreamTransformer 似乎可以让我更好地控制错误,特别是如果我想以自定义错误处理方式包装它们。
  • 完全正确:StreamTransformer 更强大,但实际上Stream.map 已经足够好了(实际上map()、expand() 和其他一些Stream 方法可以使用自定义@ 来实现987654350@,但它们作为便利方法存在)
  • 是的,您是对的,文档确实如此。我将尝试使用StreamTransformer,看看是否可以实现我正在寻找的自定义错误处理方式。说实话,我有一个 Result 类,它就像一个 Kotlin 密封类,它要么成功要么失败(借自 SealedUnions 包)。每次触发偶数时,如果一切正常,我想将其包装在Result.Success 中,否则生成一个Result.Failure,其中包含有关问题的更多详细信息(错误消息和代码+堆栈跟踪)。
  • StreamTransformer.fromHandlers 是你的朋友

标签: flutter dart async-await stream


【解决方案1】:

只需使用好的 ol' try catch,请参阅这个简化的示例:

Stream<int> inee()async*{
  try{
    for (int i = 0; i <= 5; i++) {
      if(i==4)throw Exception('Hated number 4');
   yield i;
  }
  
  }catch(e,st){
    print('Catch exception $e');
    yield 33;
  }  finally{
    //cleanup of incomplete files
  }
}
void main() {
inee().listen(print);
}

输出如下:

0
1
2
3
Catch exception Exception: Hated number 4
3

在你仍然可以让出的 catch 中,记录你的异常。您还可以将删除不完整文件的逻辑添加到 finally 块中。

【讨论】:

  • 感谢您的回答,但是有一些我不明白的地方。在您减少的示例中,您根据某个值手动抛出异常,这在我出于任何原因想自己抛出错误的情况下很好。但是我不负责的错误呢? E.g: 用户下载时网络断开 => 会导致 IO 错误,如何报告?如何捕获并包裹在自定义错误处理中?还是会在将监听我转换后的 Stream 的代码中的 onError 中报告?
猜你喜欢
  • 2015-06-07
  • 1970-01-01
  • 2021-08-05
  • 1970-01-01
  • 2014-06-28
  • 2021-10-21
  • 2023-01-05
  • 2018-11-30
  • 1970-01-01
相关资源
最近更新 更多