依赖链的API调用

问题描述 投票:1回答:2

我正在尝试链接两个API请求。一种用于生成新令牌,另一种用于获取元素列表(一个需要有效令牌)。

这些方法的调用看起来像这样:

    AuthService.shared().authenticate() { result in
        DispatchQueue.main.async {
            switch result {
               case .failure (let error):
                    // error processing
                    self.alertError(errorTitle: "", errorText: NSLocalizedString("Error generating token", comment: "Signup"))
               case .success (let result):
                    self.alertError(errorTitle: "", errorText: NSLocalizedString("Token collected \(result)", comment: "Signup"))
            }
        }
    }

    ListService.shared().listAll() { result in
        DispatchQueue.main.async {
            switch result {
               case .failure (let error):
                    // error processing
                    self.alertError(errorTitle: "", errorText: NSLocalizedString("Error fetching list", comment: "List"))
               case .success (let result):
                    self.alertError(errorTitle: "", errorText: NSLocalizedString("List fetched \(result)", comment: "List"))
            }
        }
    }

我想做的是尝试调用ListService.shared().listAll(),如果失败并出现错误,我想调用AuthService.shared().authenticate(),然后再次调用ListService.shared().listAll()

您认为这是个好方法吗?

ios swift
2个回答
0
投票

您可能会发现值得探究PromiseKit,如果不是现在,那么最终(https://github.com/mxcl/PromiseKit)。然后,您可以使用它来执行以下操作:

/**
This is just a facer for the real list all.
It will do the list all request, doing the authentication if it needs too.
*/
func listAll() {

    firstly {
        // Do the real list all
    }.recover {
        // List all failed, so we will attempt to recover

        firstly {
            // Do the authenticate
        }.then {
            // Authenticate succeeded. Do the real list all
        }
    }.done {
        // List all succeeded
    }.catch {
        // List all failed, and we tried to recover,
        // but a part of that also failed
    }
}

0
投票
  1. 混乱的方式-只需按照您指定的顺序将所有3个呼叫嵌套在一起:

    ListService.shared().listAll() { result in
        DispatchQueue.main.async {
            switch result {
            case .failure (let error):
                // error processing
                self.alertError(errorTitle: "", errorText: NSLocalizedString("Error fetching list", comment: "List"))
    
                AuthService.shared().authenticate() { result in
                    DispatchQueue.main.async {
                        switch result {
                        case .failure (let error):
                            // error processing
                            self.alertError(errorTitle: "", errorText: NSLocalizedString("Error generating token", comment: "Signup"))
                        case .success (let result):
                            self.alertError(errorTitle: "", errorText: NSLocalizedString("Token collected \(result)", comment: "Signup"))
    
                            ListService.shared().listAll() { result in
                                DispatchQueue.main.async {
                                    switch result {
                                    case .failure (let error):
                                        // error processing
                                        self.alertError(errorTitle: "", errorText: NSLocalizedString("Error fetching list", comment: "List"))
                                    case .success (let result):
                                        self.alertError(errorTitle: "", errorText: NSLocalizedString("List fetched \(result)", comment: "List"))
                                    }
                                }
                            }
                        }
                    }
                }
    
            case .success (let result):
                self.alertError(errorTitle: "", errorText: NSLocalizedString("List fetched \(result)", comment: "List"))
            }
        }
    }
    
  2. 总是尝试先进行身份验证-这可能会导致不必要的身份验证调用,但可以避免嵌套太多代码,并且比第一次失败的listAll()方法的最坏情况还好,总共3个API调用(再次为listAll()authenticate()listAll()

    AuthService.shared().authenticate() { result in
        DispatchQueue.main.async {
            switch result {
            case .failure (let error):
                // error processing
                self.alertError(errorTitle: "", errorText: NSLocalizedString("Error generating token", comment: "Signup"))
            case .success (let result):
                self.alertError(errorTitle: "", errorText: NSLocalizedString("Token collected \(result)", comment: "Signup"))
    
                ListService.shared().listAll() { result in
                    DispatchQueue.main.async {
                        switch result {
                        case .failure (let error):
                            // error processing
                            self.alertError(errorTitle: "", errorText: NSLocalizedString("Error fetching list", comment: "List"))
                        case .success (let result):
                            self.alertError(errorTitle: "", errorText: NSLocalizedString("List fetched \(result)", comment: "List"))
                        }
                    }
                }
            }
        }
    }
    
  3. 更新您的authenticate()方法以将令牌存储在本地,并在访问API之前检查其是否存在。然后更新您的listAll()方法以始终先调用authenticate()。假设您的令牌可用于多个API调用,两次调用之间不会过期,等等:

    class AuthService {
        private var token: String?

        static func shared() -> AuthService {
            return AuthService()
        }

        func authenticate(completion: @escaping (Result<String, Error>) -> Void) {
            if let token = token { 
                completion(.success(token))
                return
            }

            // Make your API call here and store the token when it completes
        }
    }

    class ListService {
        static func shared() -> ListService {
            return ListService()
        }

        func listAll(completion: @escaping (Result<Any, Error>) -> Void) {
            AuthService.shared().authenticate() { authResult in
                switch authResult {
                    case .failure (let error):
                        completion(.failure(error))
                    case .success (let token): 
                    // Make your list API call here
                }
            }
        }
    }

现在您可以像往常一样调用listAll()方法,它将始终通过身份验证:

    ListService.shared().listAll() { result in
        DispatchQueue.main.async {
            switch result {
            case .failure (let error):
                // error processing
                self.alertError(errorTitle: "", errorText: NSLocalizedString("Error fetching list", comment: "List"))
            case .success (let result):
                self.alertError(errorTitle: "", errorText: NSLocalizedString("List fetched \(result)", comment: "List"))
            }
        }
    }
© www.soinside.com 2019 - 2024. All rights reserved.