反应性设计:抛出与发布错误

时间:2017-05-23 11:48:52

标签: swift try-catch reactive-programming rx-swift

下面的代码示例有(Rx)Swift气味,但这个问题对任何具有被动功能和投掷功能的语言都是通用的。

考虑一个返回可观察序列的函数,但它在创建序列之前进行一些健全性检查。检查失败意味着序列无法生成值。

func yieldFoos() -> Observable<Foo> {
  guard isValid(internalFoo) else {
    // throw or return one shot observable?
  }
  return createValidObservable(from: internalFoo)
}

如果状态有效性检查失败,该函数是否应抛出或返回一个可观察的镜头,这将产生一个错误?我的编码员的胆量提出了这些优点和缺点:

投掷感觉逻辑上更清晰(这是一个阻止可观察创建的失败),但导致繁琐的调用代码 - catch块,不同执行范围内的多个错误处理点。

一次性观察会产生更短更干净的呼叫代码,但不知何故感觉不对。为简洁起见,观察者被迫成为非连续错误状态的载体。

任何有强烈意见的人都值得关注?还是另一个被忽视的优雅解决方案?

2 个答案:

答案 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)