Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/dart/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Asynchronous 在返回流的函数中实现异常处理_Asynchronous_Dart - Fatal编程技术网

Asynchronous 在返回流的函数中实现异常处理

Asynchronous 在返回流的函数中实现异常处理,asynchronous,dart,Asynchronous,Dart,我正在实现一个返回流的函数。我不确定如何实现错误处理,最佳实践是什么 对于返回未来的函数,这是最佳实践。对于返回流的函数也是这样吗 下面是我思考的一个例子: Stream<int> count() { var controller = new StreamController<int>(); int i = 0; try { doSomethingThatMightThrow(); new Timer.repeating(new Du

我正在实现一个返回流的函数。我不确定如何实现错误处理,最佳实践是什么

对于返回未来的函数,这是最佳实践。对于返回流的函数也是这样吗

下面是我思考的一个例子:

Stream<int> count() {
   var controller = new StreamController<int>();
   int i = 0;
   try {
     doSomethingThatMightThrow();
     new Timer.repeating(new Duration(seconds: 1), () => controller.add(i++));
   } on Exception catch (e) {
     controller.addError(e);
     controller.close();
   }
   return controller.stream;
}
流计数(){
var controller=新的StreamController();
int i=0;
试一试{
dosomethingthatthattown();
新的计时器。重复(新的持续时间(秒:1),()=>controller.add(i++);
}关于异常捕获(e){
控制器。加法器(e);
controller.close();
}
返回控制器.stream;
}

一般来说,流也是如此。其主要思想是,用户只需要以一种方式处理错误。您的示例将所有错误移动到流中

在某些情况下,即时错误会更好(例如,您可能会因为编程错误而产生错误,并且无论如何都不应处理该错误,或者如果您希望保证流不会产生错误),但通过流发送错误几乎总是一件好事


小nit:在有人开始监听之前,流通常(也有例外)不会产生任何数据。在您的示例中,您正在启动计时器,尽管您甚至不知道是否会有侦听器。我猜这个示例是简化的,不能代表您的真实代码,但它是需要注意的。解决方案是使用StreamController的回调进行暂停和订阅更改。

我更新了示例,以采纳Florian的评论

在我的实际用例中,我永远不想缓冲结果,所以如果流暂停,我将抛出一个不支持错误

我把它变成了一个终止流,而不是一个无限流

如果此函数的用户在几秒钟后异步添加侦听器,那么他们将丢失前两个结果。他们不应该这样做。我想这是需要清楚记录的东西。不过,如果订阅状态在接收到第一个数据之后,但在接收到关闭之前发生更改,我也可能抛出一个错误

Stream<int> count(int max) {
   var controller = new StreamController<int>(
           onPauseStateChange: () => throw new UnsupportedError('count() Stream pausing not supported.'));
   int i = 0;
   try {
     doSomethingThatMightThrow();
     new Timer.repeating(new Duration(seconds: 1), () {
        if (!controller.hasSubscribers)
           return;
        controller.add(i++);
        if (i >= max)
           controller.close();
     });
   } on Exception catch (e) {
     controller.addError(e);
     controller.close();
   }
   return controller.stream;
}
流计数(int max){
var控制器=新的StreamController(
onPauseStateChange:()=>抛出新的不支持错误('count()流暂停不受支持');
int i=0;
试一试{
dosomethingthatthattown();
新计时器。重复(新持续时间(秒:1),(){
如果(!controller.hasSubscribers)
返回;
controller.add(i++);
如果(i>=max)
controller.close();
});
}关于异常捕获(e){
控制器。加法器(e);
controller.close();
}
返回控制器.stream;
}

谢谢,弗洛里安。关于nit的提示很有帮助。通常,我会获取数据流,并对其进行转换和传递。如果没有侦听器,我应该吞下所有的数据,而不是将其传递。有趣,不。你不应该吞下这些数据。您应该延迟收听传入流,直到有人开始收听您的流。如果您正在转换流,请尝试将其视为订阅转换。您提供的不是原始订阅,而是一个修改后的订阅,用于转换data.Hmmm。对于我的用例,我认为这没有意义。我正在返回数据库查询的结果。如果用户不听取查询结果,我宁愿丢弃结果,也不愿永远坐在缓冲区中。理想情况下,最终用户应该调用exec(),而不是query()。但是,即使最终用户不这样做,做正确的事情也很好。我对此不确定。我会再考虑一下。很多地方都使用流,因此这条“规则”也有例外。记住这一点:您说您的数据来自另一个流。此流在有人开始侦听之前不应生成数据(同一规则)。如果您延迟侦听传入流(数据库给定的流),直到有人开始侦听您的流,您应该不会有问题。原始流是一个套接字,如果没有缓冲,我无法延迟它。