RxAlamofire + 组合信号

Posted

技术标签:

【中文标题】RxAlamofire + 组合信号【英文标题】:RxAlamofire + Combine Signals 【发布时间】:2016-03-11 18:04:13 【问题描述】:

我有一个简单的服务器请求,我想过滤并生成一个新的 Observable,用 JSON 数据验证请求。

我必须这样做,因为即使我的请求无效,我的服务器响应也会返回状态码 200。但我可以在我的 Json 响应中过滤此结果:

服务器响应:

<NSHTTPURLResponse: 0x7fb2d2617850>  URL: http://service-.herokuapp.com/--  status code: 200, headers ...

json:

"system": "code": "401","message": "Access Not Authorized"

我的 rx 请求是:

let manager = Manager.sharedInstance
return manager.rx_request(method, "\(ApiRoutes.baseURL)\(path)", parameters: parameters)
// then validate server response
.flatMap
     $0.validate(statusCode: 200..<300)
     .rx_responseData()

// then I create a new Observable validating the received json
.flatMapLatest  response, data in
     return Observable.create observer in
          let json = JSON(data: data)

          let statusCode = Int(json["system"]["code"].numberValue) ?? 400

          if 200..<300 ~= statusCode 
                observer.onNext((response,data))
          else
                observer.onError(NSError(domain: "test", code: 1, userInfo: nil))
          
          observer.onCompleted()
          return NopDisposable.instance
     

.observeOn(MainScheduler.instance)

我的问题是:当我的 json 通过(状态码在 200 到 300 之间)时,我发送一个 Event Next 并在 Event Complete 之后,这完成了这个信号并且第一个信号也完成了。但是当我在验证我的 JSON 时发送一个事件错误时,第一个信号永远不会完成或失败。我该怎么做?

谢谢

【问题讨论】:

【参考方案1】:

一个 observable 只能发送一个完成事件一个错误事件。

您需要更新您的flatMapLatest 代码以在出错后不发送onCompleted()

if 200..<300 ~= statusCode 
    observer.onNext((response,data))
    observer.onCompleted()          
else
    observer.onError(NSError(domain: "test", code: 1, userInfo: nil))


另一句话,可能会简化链:您可以在 flatMapLatest 方法中创建一个新的 Observable,而不是用抛出的 map 操作替换它

return manager.rx_request(method, "\(ApiRoutes.baseURL)\(path)", parameters: parameters)
// then validate server response
.flatMap
     $0.validate(statusCode: 200..<300)
     .rx_responseData()

.map  (response, data) in
    let json = JSON(data: data)
    let statusCode = Int(json["system"]["code"].numberValue) ?? 400

    if 200..<300 ~= statusCode 
        return (response,data)
     else 
        throw NSError(domain: "test", code: 1, userInfo: nil)
    

这样你就不需要自己处理.Next.Completed事件的转发,你的block只关注一件事,产生错误。

【讨论】:

以上是关于RxAlamofire + 组合信号的主要内容,如果未能解决你的问题,请参考以下文章

RxAlamofire - 下载完成的事件丢失

RxAlamofire:retryWhen 掉入订阅块

RxAlamofire 扩展在一处处理错误

如何使用 RxAlamofire 下载图像

删除 Swift RxAlamofire 依赖项

RxAlamofire 使用 json 正文进行 post call