趣味尝试:用 RxSwift 封装 PromiseKit then when catch

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
    }
}

你可能感兴趣的:(趣味尝试:用 RxSwift 封装 PromiseKit then when catch)