如何在RxSwift中将一种错误类型映射为另一种错误类型?
当然可以在RxSwift中实现错误类型的映射!虽然框架本身没有提供你想象中的mapError方法,但我们可以通过现有的操作符轻松实现这个需求,甚至还能封装成自定义操作符让代码更简洁。
直接使用flatMapError实现
最直接的方式是用flatMapError操作符,它专门用来处理上游抛出的错误,并返回新的Observable。针对你的场景,代码可以这么写:
func getData() -> Observable<MyData> { helper() .flatMapError { (internalError: InternalError) -> Observable<MyData> in // 根据InternalError的不同case转换为对应的ServiceError let serviceError: ServiceError switch internalError { case .fooError: serviceError = .fatalError(message: "发生了Foo类型错误") case .barError: serviceError = .warning(message: "出现了Bar类型警告") } // 返回包含转换后错误的Observable return Observable.error(serviceError) } }
flatMapError的逻辑很直观:当上游发出错误时,闭包会接收这个错误,我们在闭包里完成错误类型的转换,然后返回一个带有新错误的Observable,这样下游订阅者就会收到转换后的ServiceError了。
封装自定义mapError操作符
如果你觉得每次写flatMapError有点繁琐,想实现你最开始设想的mapError写法,我们可以给Observable写一个扩展,封装成自定义操作符:
extension Observable { func mapError<NewError: Error>(_ transform: @escaping (Error) throws -> NewError) -> Observable<Element> { return self.flatMapError { error in do { // 执行错误转换逻辑 let newError = try transform(error) return Observable.error(newError) } catch { // 如果转换过程中抛出错误,直接返回该错误 return Observable.error(error) } } } }
有了这个扩展,你就可以像最开始设想的那样调用了:
func getData() -> Observable<MyData> { helper() .mapError { (error: InternalError) -> ServiceError in switch error { case .fooError: return .fatalError(message: "Foo error occurred") case .barError: return .warning(message: "Bar error happened") } } }
额外提醒:处理意外错误类型
如果上游可能抛出非InternalError类型的错误,最好在转换前做个类型判断,避免强制转换崩溃。比如可以修改闭包里的逻辑:
.mapError { error -> ServiceError in guard let internalError = error as? InternalError else { return .fatalError(message: "未知错误:\(error.localizedDescription)") } switch internalError { case .fooError: return .fatalError(message: "Foo error occurred") case .barError: return .warning(message: "Bar error happened") } }
这样代码会更健壮,能处理意外的错误类型。
内容的提问来源于stack exchange,提问作者Yuchen
相关产品推荐
相关产品推荐

