作者:喜怒哀乐168_572 | 来源:互联网 | 2022-12-04 12:29
我有一个由多个运算符组成的序列。在此序列处理过程中,总共有7个地方可能会产生错误。我遇到了一个问题,即该序列的行为不符合我的预期,我正在寻找一种解决该问题的优雅方法:
let inputRelay = PublishRelay()
let outputRelay = PublishRelay>()
inputRelay
.map{ /*may throw multiple errors*/}
.flatmap{ /*may throw error*/ }
.map{}
.filter{}
.map{ _ -> Result in ...}
.catchError{}
.bind(to: outputRelay)
我以为那只catchError
会捕获错误,允许我将其转换为失败结果,但可以防止释放该序列。但是,我看到第一次发现错误时,将重新分配整个序列,并且不再发生任何事件。
如果没有这种行为,那么到处都会留下一个丑陋的Results <>,并且不得不多次分支我的序列以将其定向Result.failure(Error)
到输出。存在不可恢复的错误,因此retry(n)
不是一种选择:
let firstOp = inputRelay
.map{ /*may throw multiple errors*/}
.share()
//--Handle first error results--
firstOp
.filter{/*errorResults only*/}
.bind(to: outputRelay)
let secOndOp= firstOp
.flatmap{ /*may throw error*/ }
.share()
//--Handle second error results--
secondOp
.filter{/*errorResults only*/}
.bind(to: outputRelay)
secondOp
.map{}
.filter{}
.map{ _ -> Result in ...}
.catchError{}
.bind(to: outputRelay)
^这是非常糟糕的,因为大约有7个地方会引发错误,而我不能每次都保持分支的连续性。
RxSwift运算符如何捕获所有错误并在最后发出失败结果,但不将整个序列置于第一个错误上?
1> Shai Mishali..:
我想到的第一个技巧是使用materialize
。这会将每个转换Observable
为Observable>
,因此Error仅为a .next(.error(Error))
,不会导致序列终止。
但是,在这种特定情况下,还需要另一个技巧。同样,将您的整个“触发”链放入flatMap中,并materialize
进行特定处理。这是必需的,因为物化序列仍然可以完成,这在规则链的情况下会导致终止,但不会终止flatMapped链(因为flatMap内完成==成功完成)。
inputRelay
.flatMapLatest { val in
return Observable.just(val)
.map { value -> Int in
if value == 1 { throw SomeError.randomError }
return value + value
}
.flatMap { value in
return Observable.just("hey\(value)")
}
.materialize()
}
.debug("k")
.subscribe()
inputRelay.accept(1)
inputRelay.accept(2)
inputRelay.accept(3)
inputRelay.accept(4)
这将输出以下内容k
:
k -> subscribed
k -> Event next(error(randomError))
k -> Event next(next(hey4))
k -> Event next(completed)
k -> Event next(next(hey6))
k -> Event next(completed)
k -> Event next(next(hey8))
k -> Event next(completed)
现在,您要做的就是仅过滤实例化序列中的“下一个”事件。
如果您具有RxSwiftExt,则可以简单地使用errors()
和elements()
运算符:
stream.elements()
.debug("elements")
.subscribe()
stream.errors()
.debug("errors")
.subscribe()
这将提供以下输出:
errors -> Event next(randomError)
elements -> Event next(hey4)
elements -> Event next(hey6)
elements -> Event next(hey8)
使用此策略时,请不要忘记share()
在后面添加flatMap
,因此许多订阅不会引起多处处理。
您可以在此处阅读有关为何在这种情况下应该使用共享的更多信息:http : //adamborek.com/how-to-handle-errors-in-rxswift/
希望这可以帮助!