围绕网络创建反应式包装器

时间:2016-08-17 20:43:00

标签: swift alamofire reactive-programming rx-swift reactivex

在为我的网络层创建反应式扩展时,我注意到了一些模式,我想提取这些模式只是为了简化我未来实现的逻辑......所以我有什么现在有两种方法与此类似:

static func create(params: [ String: AnyObject ]) -> Observable<Type> {
    return Observable<Type>.create { observer -> Disposable in
        let request = Alamofire.request(TypeAPI.Create(params: params).responseJSON { response in
            switch response.result {
            case .Success(let value):
                guard response.response?.statusCode != 409 else {
                    observer.onError(RequestError.TypeAlreadyExists)
                    return
                }

                guard let dict = value as? [ String: AnyObject ] else {
                    observer.onError(RequestError.ParsingError)
                    return
                }

                guard let parsedType: Type = try? Unbox(dict) else {
                    observer.onError(RequestError.MappingError)
                    return
                }

                observer.onNext(parsedType)
            case .Failure(let error):
                observer.onError(RequestError.convert(error))
            }
        }

        return AnonymousDisposable {
            request.cancel()
        }
    }
}

例如AnonymousDisposable事情总是在重复。 我已经查看了RxAlamofire实现,他们的rx_request method基本上遵循了非常熟悉的模式,但当我尝试将RxAlamofire与我当前的包装器实际使用时,我有点卡住了。到目前为止,我已经结束了类似的事情:

static func rx_create(params: [ String: AnyObject ]) -> Observable<Type> {
    let manager: Manager = Manager.sharedInstance
    manager.rx_request { manager -> Request in
        return Alamofire.request(TypeAPI.Create(params: params))
    }
}

rx_request返回Observable<Request>,我需要Observable<Type>。如果我去添加.flatMap而不是我再次使用AnonymousDisposable ...

有什么建议是正确的方法吗?我至少在某个地方吗?或者我完全错了方向?

1 个答案:

答案 0 :(得分:0)

得到了一些东西......至少我猜我有所收获。它有效,现在我对这个解决方案很满意,所以让我们跳到最后。

.flatMap的路径是正确的,但要避免额外的Observable.create,我必须深入RxAlamofire,并从这个不错的rx_responseJSON方法中受益

但是后来我意识到我可以更进一步并提取这个过程,所以我已经完成了所有请求包装类的通用方法,如下所示:

static func rx_request<T>(requestConvertible: URLRequestConvertible, completion: (Request) -> Observable<T> ) -> Observable<T> {
    let manager: Manager = Manager.sharedInstance
    return manager
        .rx_request { manager -> Request in
            return Alamofire.request(requestConvertible)
        }
        .flatMap { request -> Observable<T> in
            return completion(request)
        }
        .shareReplay(1)
}

现在我可以像这里一样使用这种方法:

static func rx_create(options: String) -> Observable<Type> {
    return rx_request(TypesAPI.Create(options: options)) { request -> Observable<Type> in
        request
            .validate()
            .rx_responseJSON()
            .flatMap{ (request, json) -> Observable<Type> in
                guard
                    let dict = json as? [ String: AnyObject ],
                    let parsedType: Type = try? Unbox(dict) else {
                        return Observable.error(RequestError.ParsingError)
                }

                return Observable.just(parsedType)
            }
    }
}

在我看来哪个看起来更清洁☺️