下面的代码示例有(Rx)Swift气味,但这个问题对任何具有被动功能和投掷功能的语言都是通用的。
考虑一个返回可观察序列的函数,但它在创建序列之前进行一些健全性检查。检查失败意味着序列无法生成值。
func yieldFoos() -> Observable<Foo> {
guard isValid(internalFoo) else {
// throw or return one shot observable?
}
return createValidObservable(from: internalFoo)
}
如果状态有效性检查失败,该函数是否应抛出或返回一个可观察的镜头,这将产生一个错误?我的编码员的胆量提出了这些优点和缺点:
投掷感觉逻辑上更清晰(这是一个阻止可观察创建的失败),但导致繁琐的调用代码 - catch块,不同执行范围内的多个错误处理点。
一次性观察会产生更短更干净的呼叫代码,但不知何故感觉不对。为简洁起见,观察者被迫成为非连续错误状态的载体。
任何有强烈意见的人都值得关注?还是另一个被忽视的优雅解决方案?
答案 0 :(得分:2)
我想知道你觉得Observable发出错误是错误的。这是它的一部分工作。
当你考虑它时,你的createValidObservable(from:)
函数可能会发出错误,尽管有一个有效的internalFoo,所以调用yieldFoos()
的代码必须准备好处理发出的错误。您也可以将所有错误处理代码一起滚动。我会更进一步,让你的创建函数能够通过发出错误并取消这个yieldFoos函数来处理无效的foos本身。
现在,如果你希望yieldFoos()
返回一个Driver
而不是一个observable,然后你必须通过投掷或先决条件来处理错误(因为驱动程序不要&# 39; t发出错误。)
func yieldFoos() -> Observable<Foo> {
guard isValid(internalFoo) else {
return Observable.error(myError)
}
return createValidObservable(from: internalFoo)
}
我认为你需要克服你的感觉,即拥有一个立即返回错误的Observable是错误的。对于Observable而言,这是一个非常有效的事情,并且所有使用Observable的代码都需要准备好处理。
答案 1 :(得分:1)
你的功能应该是这样的:
func yieldFoos() -> Observable<Foo> {
Observable.create { observer in
guard isValid(internalFoo) else {
observer.onError(yourError)
}
let subscription =
createValidObservable(from: internalFoo)
.subscribe(onNext: { foo in
observer.onNext(foo)
observer.onCompleted()
})
return Disposables.create {
// your dispose
subscription.dispose()
}
}
}
然后,当你打电话给它时:
yieldFoos()
.subscribe(
onNext: { foo in
// your code with foo
},
onError: { error in
// manage errors
})
.addDisposableTo(disposeBag)