设计原理
为什么错误类型不是泛型
enum Event<Element> {
case next(Element) // 序列的下一个元素
case error(Error) // 序列因错误而失败
case completed // 序列成功终止
}
讨论泛型Error优缺点。
如果具有泛型Error类型,则会在两个可观察对象之间不匹配。
假设有:
Observable<String, E1> 和 Observable<String, E2>
如果没有弄清楚错误类型将导致很多事情。
它会是E1,E2还是一些新的E3?因此,需要一组新的操作符来解决不匹配问题。
这会破坏组合属性,而Rx并不关心序列失败的原因,它通常只会在可观察链上进一步转发。
还有一个问题是,在某些情况下,操作符可能会因某些内部错误而失败,在这种情况下,将无法构造错误结果并报告失败。
好吧,先忽略这些,并假设使用它来模拟没有错误输出的序列。它可以用于此目的吗?
是的,它可能,但为什么要使用没有错误的序列。
一个明显的应用是用于驱动整个UI的UI层中的永久流。当你考虑这种情况时,仅仅使用编译器来证明序列没有错误就不够了,还需要证明其他属性。例如,在MainScheduler中observed on这些元素。
真正需要证明是一个可观察序列traits的泛型方法。可能会对很多属性感兴趣。例如:
- 序列在有限时间内终止(服务器端)
- sequence只包含一个元素(如果正在运行一些计算)
- 序列没有错误输出,永远不会终止,元素在主调度程序(UI)上传递
- 序列没有错误输出,永远不会终止,元素在主调度程序上传递,并具有refcounted共享(UI)
- 序列没有错误输出,永远不会终止,元素在特定的后台调度程序(音频引擎)上传递
真正想要的是一个编译器强制的泛型可观察序列traits系统,以及一组那些所需属性的不可变操作符。
一个很好的比喻是:
1, 3.14, e, 2.79, 1 + 1i <-> Observable<E>
1m/s, 1T, 5kg, 1.3 pounds <-> Errorless observable, UI observable, Finite observable ...
通过使用可观察对象的组合或继承,有许多方法可以在Swift中执行此类操作。
使用系统单位的另一个好处是,可以证明UI代码在同一个调度程序上执行,因此对所有转换使用无锁运算符。
由于RxSwift已经没有用于single sequence 操作的锁,并且所有存在的锁都在有状态组件(例如UI)中,因此RxSwift代码中几乎没有锁,由于这些细节允许编译器强制执行。
在保留Rx组合语义的同时,无法使用其他更干净的方式实现的Error类型确实没有任何好处。
网友评论