为什么rx有以下语法OnNext* (OnError|OnCompleted)
?而不是(OnNext|OnError)* OnCompleted
?从实施角度来看,这很明显(这也具有IEnumerable
和yield
的常见语义),但我猜与现实生活中的情况有所不同。在现实生活中 - 生产商会产生混合的数据和异常流(并且例外不会破坏生产者)。
问题:如果我正确理解,唯一可能的解决方案是使可观察的返回复杂数据结构从初始数据和产生的异常(Observable.Timestamp()
和.TimeInterval()
具有相似的概念)合并在一起,或者是否还有其他选项?
目前我提出了以下解决方案:在可观察的生产者内部,我手动处理exeptions,然后将它们传递到以下数据结构,这是我可观察的
的结果public class ValueOrException<T>
{
private readonly Exception ex;
private readonly T value;
public ValueOrException(T value, Exception ex)
{
this.value = value;
this.ex = ex;
}
public ValueOrException(T value)
{
this.value = value;
}
public T Value
{
get { return this.value; }
}
public Exception Ex
{
get { return this.ex; }
}
}
如果消费者是一个知道Exception
是否期望的人,那么我说 throwing 例外是不正确的。
您本质上是在试图传达状态或逻辑,这并不是要做的。例外是为了将系统(或至少,当前操作)带到磨碎的停顿,因为发生了某些事情,代码本质上不知道如何从中恢复。
在这种情况下,碰巧的是,您的业务逻辑/状态的 Exception
是 part ,但这并不意味着您可以扔它们。您需要将它们传递给您的消费者,然后将消费者处理它们。
Tuple<T, Exception>
在这里捏合起来,但是类型上缺乏特异性(以及属性)通常是混乱的,因此我建议创建专用类型来传达您的操作结果并暴露出来通过IObservable<T>
。
onerror的意思是消息,即发生不可恢复的错误,因此应重置流。恢复后,在例外事件的情况下,下一个事件是没有意义的。
例如,考虑事件流:
- 用户加入聊天
- 用户加入聊天
- !! 聊天崩溃了,以便所有用户都被踢了
- 用户加入聊天
现在,流消费者使用聚合功能显示chat不休的数量。最后应该显示什么?当然1,而不是3。
valueorexception看起来像功能编程中的任何一种类型。您只是左右交换。按照惯例右边是成功的。