如何使用 Moya RxSwift 合并 REST 数组

Posted

技术标签:

【中文标题】如何使用 Moya RxSwift 合并 REST 数组【英文标题】:how to use Moya RxSwift to get an array of REST merged 【发布时间】:2019-05-31 19:11:16 【问题描述】:

我正在尝试学习 RxSwift。我一直在使用 Moya,现在想试试 RxSwift。完全糊涂了。

 let popServiceProvider = MoyaProvider<PopRESTService>()
    let o1 = popServiceProvider.rx.request(.getPopByCity(city: "London")).asObservable()
    let o2 = popServiceProvider.rx.request(.getPopByCity(city: "Tokyo")).asObservable()

    let pObservables:[Observable<Response>] = [o1, o2]
    let stats: Observable<Response> = Observable.combineLatest(pObservables)
    let m = stats.map( a in
        print(a)
    )  

首先我在 let stats 上得到一个错误:

无法将'Observable'类型的值转换为指定类型'Observable'

我是否朝着正确的方向前进?

编辑:

即使这样也行不通。永远不要先订阅:

   wServiceProvider.rx.request(.getWeatherByCity(city: "Chicago"))
    .debug()
    .map(Weather.self)
    .subscribe( (event) in
        switch event 
        case let .success(response):
            print(response)

        case let .error(response):
            print(response)
        
    )
    .disposed(by: self.disposeBag)

【问题讨论】:

【参考方案1】:

我建议使用combineLatestObservable.combineLatest(o1, o2) 变体(这种形式受8 个参数的限制)

假设从 case getPopByCity(city: String) 返回的类型可能如下所示:

struct PopByCity: Decodable 
  let count: Float

您可能希望这样实现请求:

Observable.combineLatest(o1, o2)
  .map  (resp1: Response, resp2: Response) -> [PopByCity] in
    let pop1 = try? JSONDecoder().decode(PopByCity.self, from: resp1.data)
    let pop2 = try? JSONDecoder().decode(PopByCity.self, from: resp2.data)
    return [pop1, pop2].compactMap  $0 
  
  .subscribe(onNext:  (result: [PopByCity]) in
    print(result)
  )
  .disposed(by: disposeBag)

但是如果你还需要一个请求数组:

Observable.combineLatest([o1, o2])
  .map  (responses: [Response]) -> [PopByCity] in
    responses.map  try? JSONDecoder().decode(PopByCity.self, from: $0.data) 
      .compactMap  $0 
  
  .subscribe(onNext:  (result: [PopByCity]) in
    print(result)
  )
  .disposed(by: disposeBag)

对于第二个选项,请记住,同时发送大量异步请求不是一个好习惯。对于需要执行的许多请求,如果您必须在最后一个响应之后在一个地方处理所有响应,我建议使用 Concat 运算符或 Concat + Reduce 的组合。

【讨论】:

我尝试了您的代码并在其他尝试中遇到了同样的问题:添加 debug() 告诉我“已订阅”,但在 .subscribe 中没有运行任何内容。 嗯,我不确定我是否正确,也许执行请求存在一些问题。如果我将o1o2 更改为模拟Single API 调用的Observable,例如swift let o1 = Single&lt;PopByCity?&gt; .just(PopByCity(count: 5000)) .delay(1, scheduler: MainScheduler.instance) .asObservable() .debug("o1") ,您可以分享的任何代码都将有助于澄清问题。我不知道你的模型结构是什么样的,或者你如何将Response 映射到模型。【参考方案2】:

我对 Apple XCTest 的误解。我需要补充:

                expectation.fulfill()

在我的订阅中。

Observable.combineLatest([o1, o2])
        .map  (responses: [Response]) -> [Weather] in
            responses.map  try? JSONDecoder().decode(Weather.self, from: $0.data) 
                .compactMap  $0 
        
        .debug()
        .subscribe(onNext:  (result: [Weather]) in
            print(result)
            expectation.fulfill()

        )
        .disposed(by: disposeBag)

【讨论】:

以上是关于如何使用 Moya RxSwift 合并 REST 数组的主要内容,如果未能解决你的问题,请参考以下文章

moya 与 RxSwift 使用

RxSwift+Moya+Moya_ObjectMapper+MJRefresh,刷新失败?

RxSwift + Moya + ObjectMapper

RxSwift + Moya + ObjectMapper

处理 UITableView 绑定中的连接错误(Moya、RxSwift、RxCocoa)

RxSwift/Moya - 如果通过函数返回序列将不会启动