Search code examples
swiftrx-swiftmoya

How properly filterSuccessfulStatusCodes in RxMoya


Im using RxMoya and I was wondering about usage of fiterSuccesfulStatusCodes, I will try to describe what my problem is...So when you use some Network call like this

func getAllApps(gwId: Int) -> Observable<Response> {
    return provider.request(RestAPI.GetAllApps(gwId: gwId)).filterSuccessfulStatusCodes()
}

When you get response with status code above 299 nothing will happen, my problem is that I would like to display error message to user, but when you inspect what does filterSuccessfulStatusCodes do:

public func filterSuccessfulStatusCodes() -> Observable<E> {
    return flatMap { response -> Observable<E> in
        return Observable.just(try response.filterSuccessfulStatusCodes())
    }
}

Now we are getting closer to the problem I have. So implementation of filterSuccessfulStatusCodes uses public instance function of Moya.Resposne with this implementation :

public func filterSuccessfulStatusCodes() throws -> Response {
    return try filterStatusCodes(200...299)
}

As you can see, this thing throws exceptions...but the function above, it doesnt rethrow, it returns Observable of generic type E.

My first question, How come you can use return Observable.just(try response.filterSuccessfulStatusCodes()) when the function doesnt throw/rethrow. You can use try withou do/chatch?(I know with try!/try? you can but with try, I can only imagine case with rethrow).

Second question, it there a way to react to error status codes, on the level of observables.

Thank you


Solution

    • try response.filterSuccessfulStatusCodes() is not use in the scope of filterSuccessfulStatusCodes() but in flatMap.

      If we take a look at the definition of flatMap on Observable we get

      func flatMap<O: ObservableConvertibleType>(_ selector: @escaping (E) throws -> O)
        -> Observable<O.E>
      

      selector here throws, so we can use try.

    • When something throws in the observable chain, the observable will end with an error. So you'll be able to react to unsuccessful status code in the onError selector of the subscribe call (or using catch, retry and other operators that act on errors).

      getAllApps(gwId: Int)
        .subscribe(onNext: {
          debugPrint("Success with \($0)")
        }, onError: { error in
          switch error {
          case Moya.Error.statusCode(let response):
            debugPrint("Invalid status code \(response.statusCode)")
          default:
            debugPrint("An error occured: \(error)")
          }
        })