не может вернуть наблюдаемую ошибку customError в сетевом вызове - PullRequest
0 голосов
/ 15 октября 2018

Я хочу использовать catchError для возврата моей ошибки как пользовательского типа.Сначала я хочу, чтобы мой сетевой уровень возвратил Observable, а затем в ViewModel я подписал его на события .OnNext, .OnError, .OnCompleted, но я не знаю, как я должен обрабатывать ошибки, такие как 4xx, код состояния сети 5xx, а затем,они возвращают мой пользовательский объект ошибки!

Мой логин ViewModel:

func getAccessToken() {        
        let network = NetworkRequest()

        network.logInRequest(tokenType: .guest, token: "cce577f6021608", secondKey: "09128147040", client: "cce577f6021608bc31424d209cbf5120c3683191").subscribe(onNext: { loginData in
            self.token.onNext(loginData.access_token)
        }, onError: { error in
            print("The Error is: \(error.localizedDescription)")
        }, onCompleted: {
            print("Its Completed")
        }).disposed(by: bag)
    }

Моя функция сетевого уровня:

class NetworkRequest: NSObject {
    var rxProvider: MoyaProvider<WebServiceAPIs>

    override init() {
        rxProvider = MoyaProvider<WebServiceAPIs>( plugins: [ NetworkLoggerPlugin(verbose:true) ])
    }

    func logInRequest(tokenType: accessTokenTypeEnum, token: String, secondKey: String, client: String) -> Observable<LoginModel> {
        return rxProvider.rx
              .request(WebServiceAPIs.getAccessToken(tokenType: tokenType.rawValue, token: token, secondKey: secondKey, client: client))
              .filterSuccessfulStatusCodes()
              .catchError({ error -> Observable<NetworkError> in
                return //Observable.just() => I want to return a custom network error as obserable 
              })
              .map(LoginModel.self, atKeyPath: nil, using: JSONDecoder(), failsOnEmptyData: true).asObservable()
    }

}

спасибо за любую помощь

Ответы [ 2 ]

0 голосов
/ 15 октября 2018

По моему опыту, оператор ' .materialize () ' является идеальным решением для обработки ошибок HTTP.Вместо отдельных событий для успеха и ошибки вы получаете одно событие-обертку, в которое вложены либо успех, либо ошибка.

0 голосов
/ 15 октября 2018

Moya возвращает перечисление MoyaError в блоке ошибок, который можно обработать, извлекая тип ошибки, используя переключатель на MoyaError, а затем используя statusCode для преобразования в перечисление NetworkError

func logInRequest(tokenType: accessTokenTypeEnum, token: String, secondKey: String, client: String) -> Observable<LoginModel> {
        return sharedProvider.rx
                .request(WebServiceAPIs.getAccessToken(tokenType: tokenType.rawValue, token: token, secondKey: secondKey, client: client))
                .filterSuccessfulStatusCodes()
                .catchError({ [weak self] error -> Observable<NetworkError> in
                    guard let strongSelf = self else { return Observable.empty() }
                    if let moyaError = error as? MoyaError {
                        let networkError = self?.createNetworkError(from: moyaError)
                        return Observable.error(networkError)
                    } else {
                        return Observable.error(NetworkError.somethingWentWrong(error.localizedDescription))
                    }
                })
                .map(LoginModel.self, atKeyPath: nil, using: JSONDecoder(), failsOnEmptyData: true).asObservable()
    }

    func createNetworkError(from moyaError: MoyaError) -> NetowrkError {
        switch moyaError {
        case .statusCode(let response):
            return NetworkError.mapError(statusCode: response.statusCode)
        case .underlying(let error, let response):
            if let response = response {
                return NetworkError.mapError(statusCode: response.statusCode)
            } else {
                if let nsError = error as? NSError {
                  return NetworkError.mapError(statusCode: nsError.code)
                } else {
                  return NetworkError.notConnectedToInternet
                }
            }
         default:
              return NetworkError.somethingWentWrong("Something went wrong. Please try again.")
        }
    }

Вы можете создать свой собственный перечисление NetworkError, как показано нижекоторый будет сопоставлять statusCode с пользовательским значением перечисления NetworkError.Он будет иметь errorDescription var, который будет возвращать пользовательское описание, отображаемое в виде ошибки

enum NetworkError: Swift.Error {
    case unauthorized
    case serviceNotAvailable
    case notConnectedToInternet
    case somethingWentWrong(String)

    static func mapError(statusCode: Int) -> NetworkError {
        switch statusCode {
        case 401:
            return .unauthorized
        case 501:
            return .serviceNotAvailable
        case -1009:
            return .notConnectedToInternet
        default:
            return .somethingWentWrong("Something went wrong. Please try again.")
        }
    }

    var errorDescription: String {
        switch self {
        case .unauthorized:
            return "Unauthorised response from the server"
        case .notConnectedToInternet:
            return "Not connected to Internet"
        case .serviceNotAvailable:
            return "Service is not available. Try later"
        case .somethingWentWrong(let errorMessage):
            return errorMessage
        }
    }
}
...