我读过一些帖子说处理 RxSwift 的最佳实践是只将 fatal error 传递给 onError 并将结果传递给 onNext。
这对我来说很有意义,直到我意识到我无法再处理重试,因为它只发生在 onError 上。
我该如何处理这个问题?
另一个问题是,如何同时处理全局和本地重试混合?
例如,iOS 收据验证流程。
1、尝试在本地获取收据
2、如果失败,向苹果服务器索取最新收据。
3、将收据发送到我们的后台进行验证。
4、如果成功,则整个流程完成
5、如果失败,检查错误码是否可重试,然后返回1。
而在新的 1 中,它会强制从苹果服务器请求新的收据。然后当它再次达到 5 时,整个流程将停止,因为这已经是第二次尝试了。意味着只重试一次。
所以在这个例子中,如果使用状态机而不使用 rx,我将最终使用状态机并共享一些全局状态,如 isSecondAttempt: Bool
、shouldForceFetchReceipt: Bool
等
我如何在 rx 中设计这个流程?这些全局共享状态是在流程中设计的。
最佳答案
I read some post says that the best practice to deal with RxSwift is to only pass fatal error to the onError and pass Result to the onNext.
我不同意这种观点。它基本上是说,如果程序员犯了错误,你应该只使用 onError
。您应该将错误用于不愉快的路径或中止过程。它们就像以异步方式抛出。
这是作为 Rx 链的算法。
enum ReceiptError: Error {
case noReceipt
case tooManyAttempts
}
struct Response {
// the server response info
}
func getReceiptResonse() -> Observable<Response> {
return fetchReceiptLocally()
.catchError { _ in askAppleForReceipt() }
.flatMapLatest { data in
sendReceiptToServer(data)
}
.retryWhen { error in
error
.scan(0) { attempts, error in
let max = 1
guard attempts < max else { throw ReceiptError.tooManyAttempts }
guard isRetryable(error) else { throw error }
return attempts + 1
}
}
}
下面是上面使用的支持函数:
func fetchReceiptLocally() -> Observable<Data> {
// return the local receipt data or call `onError`
}
func sendReceiptToServer(_ data: Data) -> Observable<Response> {
// send the receipt data or `onError` if the server failed to receive or process it correctly.
}
func isRetryable(_ error: Error) -> Bool {
// is this error the kind that can be retried?
}
func askAppleForReceipt() -> Observable<Data> {
return Observable.just(Bundle.main.appStoreReceiptURL)
.map { (url) -> URL in
guard let url = url else { throw ReceiptError.noReceipt }
return url
}
.observeOn(ConcurrentDispatchQueueScheduler(qos: .userInitiated))
.map { try Data(contentsOf: $0) }
}
关于ios - 处理 RxSwift 重试和错误处理的最佳实践是什么,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54762921/