2017-05-23 27 views
1

以下代碼示例具有(Rx)Swift的氣味,但對於具有反應性特徵和拋出功能的任何語言而言,該問題是通用的。無功設計:拋出與發佈錯誤

考慮一個返回可觀察序列的函數,但它在創建序列之前會進行一些理智檢查。檢查失敗意味着序列不能產生值。

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

在狀態有效性檢查失敗的情況下,應函數拋出或返回一個鏡頭觀察到,這都不會產生只是一個錯誤?我的編碼器的膽量提出了這些優點和缺點:

投擲感覺邏輯上更清潔(這是一種失敗,防止可觀察的創建),但會導致繁瑣的調用代碼 - catch塊,多個錯誤處理點在不同的執行範圍。

一次可觀察結果導致更短,更乾淨的調用代碼,但不知何故感覺錯誤。爲了簡潔起見,可觀察元素被迫成爲非順序錯誤狀態的載體。

任何有強烈意見值得關注的人?還是另一個被忽視的優雅解決方案?

回答

2

我不知道你的感覺,這是錯誤的,可觀察到發出錯誤。這是它的一部分工作。

當你考慮這個問題時,儘管交給了一個有效的internalFoo,你的createValidObservable(from:)函數可能會發出一個錯誤,所以調用yieldFoos()的代碼必須準備好處理髮出的錯誤。你可能把所有的錯誤處理代碼放在一起。我會更進一步,讓你的創建函數能夠通過發出錯誤並消除這個yieldFoos函數來處理無效的foos本身。現在

,如果你想yieldFoos()返回一個Driver,而不是一個可觀察的,然後你必須通過投擲或前提,以處理錯誤(因爲司機不發出錯誤。)

func yieldFoos() -> Observable<Foo> { 
    guard isValid(internalFoo) else { 
     return Observable.error(myError) 
    } 
    return createValidObservable(from: internalFoo) 
} 

我認爲你需要克服你有一個立即返回錯誤的Observable錯誤的感覺。這對於Observable來說是完全有效的,而且所有使用Observable的代碼都需要準備好處理。

+0

Observable發出錯誤並沒有錯。我只是覺得這樣的錯誤應該是「可觀察的」(無法繼續順序),而不是首先創建觀察值。序列失敗是正常的,創造失敗是一個特殊的不一致,因此投擲似乎是適當的。但是單擊「Observable.error」運算符的存在暗示我可能只是在想太多。 –

+0

如果您的創建函數傳遞了一個無效的internalFoo,它將無法繼續序列... :-)它可能有助於將Observable錯誤視爲它們的throw版本,或將其視爲異步事件的throw 。它的工作方式就像一個投入,它通過管道傳播,直到它被處理... –

+0

所以你會這樣說 - 在反應式代碼中,拋出一般情況下的用例較少?我認爲一個關鍵的反應性概念是,一切都可能逐漸異步甚至是懶惰,但是你的轉換代碼不應該在意。而拋出本質上是同步的...... –

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) 
+1

我知道如何構建和使用observables,謝謝。我在問是否應該拋出或按順序排除特殊的失敗。你似乎喜歡序列,但沒有推理。 –