RxSwift 原生的 flatmap 和 map 其实就可以达到 then 的效果, 但是毕竟用法上有些许区别, 为了熟悉 RxSwift , 我自己写了一个小小的 extension 实现 then catch 和 when 等 Promise 概念中的方法, 让我对 Rx 有了更深一步的认识和理解 import Foundation import RxSwift protocol RxResultType { associatedtype E } enum RxResult: RxResultType { typealias E = T case fulfilled(T) case rejected(Error) } extension Observable { static func when(resolved collection: C) -> Observable<[RxResult]> where C.Iterator.Element: ObservableType, C.Iterator.Element.E == Element { let transformCollection: [Observable>] = collection.map({ $0.map({ (element) -> RxResult in return RxResult.fulfilled(element) }).catchError({ (error) -> Observable> in return .just(RxResult.rejected(error)) }) }) return Observable>.combineLatest(transformCollection) } func then(execute body: @escaping (Element) throws -> Observable) -> Observable { let subject = ReplaySubject>.create(bufferSize: 1) _ = self.do(onNext: { (element) in do { subject.onNext(try body(element)) } catch let err { subject.onError(err) } }, onError: { (error) in subject.onError(error) }).subscribe() let resultSubject = ReplaySubject.create(bufferSize: 1) _ = subject.subscribe(onNext: { (observable) in _ = observable.subscribe(onNext: { (result) in resultSubject.onNext(result) }, onError: { (error) in resultSubject.onError(error) }) }, onError: { (error) in resultSubject.onError(error) }) return resultSubject } func then(execute body: @escaping (Element) throws -> R) -> Observable { let subject = ReplaySubject>.create(bufferSize: 1) _ = self.do(onNext: { (element) in do { subject.onNext(.just(try body(element))) } catch let err { subject.onError(err) } }, onError: { (error) in subject.onError(error) }).subscribe() let resultSubject = ReplaySubject.create(bufferSize: 1) _ = subject.subscribe(onNext: { (observable) in _ = observable.subscribe(onNext: { (result) in resultSubject.onNext(result) }, onError: { (error) in resultSubject.onError(error) }) }, onError: { (error) in resultSubject.onError(error) }) return resultSubject } func then(execute body: @escaping (Element) throws -> Void) -> Observable { let subject = ReplaySubject>.create(bufferSize: 1) _ = self.do(onNext: { (element) in do { try body(element) subject.onNext(Observable.just()) } catch let err { subject.onError(err) } }, onError: { (error) in subject.onError(error) }).subscribe() let resultSubject = ReplaySubject.create(bufferSize: 1) _ = subject.subscribe(onNext: { (observable) in _ = observable.subscribe(onNext: { (result) in resultSubject.onNext(result) }, onError: { (error) in resultSubject.onError(error) }) }, onError: { (error) in resultSubject.onError(error) }) return resultSubject } func `catch`(body: @escaping (Error) -> Void) -> Observable { let subject = ReplaySubject>.create(bufferSize: 1) _ = self.subscribe(onNext: { (element) in subject.onNext(Observable.just(element)) }, onError: { (error) in body(error) subject.onError(error) }) let resultSubject = ReplaySubject.create(bufferSize: 1) _ = subject.subscribe(onNext: { (observable) in _ = observable.subscribe(onNext: { (result) in resultSubject.onNext(result) }, onError: { (error) in resultSubject.onError(error) }) }, onError: { (error) in resultSubject.onError(error) }) return resultSubject } }