0

I've started to use PromiseKit in async requests and I have a problem for now, I can't parse an error in chain. I have an request manager with method like this:

func request(
        url: String,
        parameters: JSON? = nil,
        requestMethod: HTTPMethod,
        completion: @escaping completion
    ) {
        self.logger.log(category: .network, message: "Starting request", access: .public)
        Alamofire.request(
            url,
            method: requestMethod,
            parameters: parameters,
            encoding: JSONEncoding.prettyPrinted
        ).responseData { response in
            if let data = response.data {
                self.logger.log(category: .network, message: "Response: \(data)", access: .private)
                completion(.success(data))
            } else {
                self.logger.log(category: .network, message: SWError.dataError.localizedDescription, access: .public, type: .error)
                completion(.failure(SWError.dataError))
            }
        }
    }

The request is creating like this:

public class func getSettings(
        completion: @escaping (Result<Model.Settings.Settings>) -> Void
        ) {
        RequestManager.shared.request(
            url: Endpoint.Settings.slash.url(),
            requestMethod: .get
        ) { result in
            switch result {
            case let .success(data):
                do {
                    let result = try JSONDecoder().decode(Model.Settings.Settings.self, from: data)
                    completion(.success(result))
                } catch {
                    Request.Shared.handleCode(from: data, completion: { serverCode in
                        logger.log(category: .network, message: SWError.decodingError.localizedDescription, access: .public, type: .error)
                        completion(.failure(serverCode))
                    })
                }
            case let .failure(error):
                completion(.failure(error))
            }
        }
    }

Promise part is here:

private func getAppSettings() -> Promise<[Model.Settings.Datum]> {
        return Promise { seal in
            Request.Settings.getSettings(completion: { result in
                switch result {
                case let .success(model):
                    if let data = model.data {
                        seal.fulfill(data)
                    } else {
                        seal.reject(SWError.create(with: "No app settings data"))
                    }
                case let .failure(error):
                    seal.reject(error)
                }
            })
        }
    }

Somehow I can't catch error. What is wrong with my request? How to make it right?

1 Answers1

0

Replace CompletionHandler in Request and getSettings with Promises. I have modified this to some extent based on my understanding.

Modify

func request(url: String,
             parameters: JSON? = nil,
             requestMethod: HTTPMethod,
             completion: @escaping completion)

to

func request(url: String,
             parameters: JSON? = nil,
             requestMethod: HTTPMethod) -> Promise<[Model.Settings.Datum]> {
    return Promise { seal in

    self.logger.log(category: .network, message: "Starting request", access: .public)
    Alamofire.request(
        url,
        method: requestMethod,
        parameters: parameters,
        encoding: JSONEncoding.prettyPrinted
        ).responseData { response in
            if let data = response.data {
                self.logger.log(category: .network, message: "Response: \(data)", access: .private)
                seal.fulfill(data)
            } else {
                self.logger.log(category: .network, message: SWError.dataError.localizedDescription, access: .public, type: .error)
                seal.reject(.failure(SWError.dataError))
            }
        }
    }
}

And also modify

public func getSettings( completion: @escaping (Result<Model.Settings.Settings>) -> Void)

to

public func getSettings() -> Promise<[Model.Settings.Settings]>  {
    return Promise { seal in

    RequestManager.shared.request(
        url: Endpoint.Settings.slash.url(),
        requestMethod: .get).then { data in
            do {
                let result = try JSONDecoder().decode(Model.Settings.Settings.self, from: data)
                seal.fulfill(result)
            } catch {
                Request.Shared.handleCode(from: data).then { serverCode in
                    logger.log(category: .network, message: SWError.decodingError.localizedDescription, access: .public, type: .error)
                    seal.reject(.failure(serverCode))
                }
            }
    }
}

After modifying, use these methods in getAppSettings so that Error cases can be successfully catched.

func getAppSettings() -> Promise<[Model.Settings.Datum]> {
    return Promise { seal in
        Request.Settings.getSettings.then { model in
            if let data = model.data {
                seal.fulfill(data)
            } else {
                seal.reject(SWError.create(with: "No app settings data"))
            }
        }
    }
}
Anand
  • 1,820
  • 2
  • 18
  • 25
  • Is there a way to escape rewrite all base request code? Or promise kit is working bad with closures? – Igor Kandaurov Apr 09 '19 at 10:42
  • Can you please let me know, from which method you are not able to parse error in the chain? Error can happen at request method, getSettings method or getAppSettings method. BTW, promise kit is not that bad with closures. You can still use it with completion handlers. I just suggested a way in order to have cleaner code without mixing completion handler and promises so that the chances of missing the chain are less. – Anand Apr 09 '19 at 12:02
  • I still can't figure out how to solve this... I just refactored this pieces but still no error. It looks like do {} catch {} block when in new Promise handles after fulfill... Can we contact somehow? – Igor Kandaurov Apr 15 '19 at 11:25