使用RxSwift重播上一个请求

时间:2019-01-24 08:46:27

标签: swift networking rx-swift

我正在创建一个网络层,在其中注入API提供程序并将事件调用给initialize方法。

class NetworkingLayer<T: Decodable, E: TargetType> {

    var response: Driver<T>

    init(provider: MoyaProvider<E>, request: Singal<E>) {

        let requestState = request
            .flatMapLatest({
                provider.rx.request($0).map(Respose<T>.self)
                    .map { ReqestState.loaded($0) }
                    .asDriver(onErrorRecover: { error  in
                        return Driver.just(.error(error))
                    })
                    .startWith(.loading)
            })
            .asDriver(onErrorRecover: { fatalError($0.localizedDescription) })

        response = requestState
            .map({ $0.data?.data })
            .filterNil()

    }
}

通过以下方式使用它们:

class ViewModel {

    let networking: DataNetworkingResponse<[TagItem], ScoutEnpoint>

    init(provider: MoyaProvider<Endpoint>, event: Singal<[Int]>) {

        let request = event
            .map({ Endpoint.getNewItems(prevItemsIds: $0) })

        self.networking = NetworkingLayer(provider: provider, request: request)
    }
}

所有工作都像魅力。但是现在我必须实现刷新功能。刷新我的上一个请求。我已将此let refresh: Signal<()> = Signal.empty()属性添加到我的网络层。但是不知道如何保存我的上一个请求。

class NetworkingLayer<T: Decodable, E: TargetType> {

    let refresh: BehaviorRelay<()> = BehaviorRelay.init(value: ())
    ...
}

如何实现这样的刷新?

viewModel.networking.refresh.accept(())

1 个答案:

答案 0 :(得分:0)

使用BehaviorRelay是一个坏主意,因为它在订阅后会立即发出一个值。这意味着您的NetworkingLayer对象将在构造后立即发出请求。

更好的方法是将另一个Signal传递到init方法中:

init(provider: MoyaProvider<E>, request: Singal<E>, refresh: Signal<Void>)

我不了解Moya,但是这就是我使用URLSession编写类似内容的方法:

enum RequestState<T> {
    case loaded(T)
    case error(Error)
    case loading
}

class NetworkingLayer<T: Decodable> {

    let response: Driver<RequestState<T>>

    init(request: Signal<URLRequest>, refresh: Signal<Void>, provider: URLSession = URLSession.shared, decoder: JSONDecoder = JSONDecoder()) {
        response = Observable.merge(request.asObservable(), refresh.withLatestFrom(request).asObservable())
            .flatMapLatest { request in
                provider.rx.data(request: request)
                    .map { try decoder.decode(T.self, from: $0) }
                    .map { RequestState.loaded($0) }
                    .startWith(.loading)
                    .catchError { Observable<RequestState<T>>.just(.error($0)) }
            }
            .share(replay: 1)
            .asDriver(onErrorRecover: { fatalError($0.localizedDescription) })
    }
}

我把share(replay:)放在那儿,这样以后的订户就不会发出单独的网络请求,并且我使解码器可注入,以便调用者可以根据需要配置它。