Home > Blockchain >  How can I handle the bad url error using combine?
How can I handle the bad url error using combine?

Time:05-24

I am using combine to handle the network response. I am stuck here to handle the common errors. Can you please help me how Can I handle the errors.

func performRequest<T:Decodable>(router:APIConfiguration, decodeType:T.Type) ->AnyPublisher<DataResponse<T, NetworkError>, Never> {
    guard let url = URL.init(string: router.requestedURL) else {
        return Fail(error: NetworkError.init(code: 2345, message: "Bad URL")).eraseToAnyPublisher()
    }
    let storage = KeycheinStorage()
    print(router.requestedURL,router.parameters ?? [:])
    return AF.request(router.requestedURL, method: router.method, parameters: router.parameters, interceptor: AuthTokenInterceptor(storage: storage))
        .validate()
        .publishDecodable(type: T.self)
        .map { response in
            response.mapError { error in
                let networkError = response.data.flatMap {
                    try? JSONDecoder().decode(NetworkError.self, from: $0)
                } ?? NetworkError(error)
                ErrorHandler.default.handle(networkError)
                return networkError
            }
        }
        .receive(on: DispatchQueue.main)
        .eraseToAnyPublisher()
}

enter image description here

CodePudding user response:

The issue is that the method you are building specifies that it never will return an error, but then you try to do exactly that. You are defining Never as the failure type in the return types of your method declaration:

func performRequest<T:Decodable> ... -> AnyPublisher<DataResponse<T, NetworkError>, Never>

You can fix that by not using Never, but for example Error like this:

func performRequest<T:Decodable> ... -> AnyPublisher<DataResponse<T, NetworkError>, Error>

Then you will be able to send any error in the publisher.

CodePudding user response:

As suggested by @Joakim Danielson, you can use Just here, you just need to wrap your NetworkError in a DataResponse. Unfortunately there's no convenient initializer, so you need to be pretty verbose.

Just(DataResponse<T, NetworkError>(request: nil, 
                                   response: nil, 
                                   data: nil, 
                                   metrics: nil, 
                                   serializationDuration: 0, 
                                   result: .failure(<your error>))

However, instead of doing that I suggest you simply adopt Alamofire's URLRequestConvertible for your APIConfiguration type so Alamofire can handle the URL checking and error production for you.

Additionally, Alamofire's completion handlers and even publishers complete on the main queue by default, so the receive(on:) call is unnecessary.

  • Related