【问题标题】:How to call multiple Api based on the previous Api success如何根据之前的Api成功调用多个Api
【发布时间】:2022-10-12 22:50:27
【问题描述】:

我想在同一个屏幕上进行多个 API 调用,但是当一个 api 失败时,不应该调用其他 api?下面的代码工作正常。但我需要的是,如何以更简单的方式重构它?

      ApplicationService.requestAppEndPointUrl { success, error in
        if success {
            ApplicationService.appLinkDownload { success, error in
                if success{
                    ApplicationService.requestApplicationSession { success, error in
                        if success {
                            ApplicationService.validateSdk { success, error in
                                if success {
                                    ApplicationService.requestApplicationDetails { success, error in
                                        if success{
                                            print("Success")
                                        }
                                        else{
                                            self.showErrorAlert(error)
                                        }
                                    }
                                }else{
                                    self.showErrorAlert(error)
                                }
                            }
                        }else{
                            self.showErrorAlert(error)
                        }
                    }
                }else{
                    self.showErrorAlert(error)
                }
            }
        }else{
            self.showErrorAlert(error)
        }
    }

【问题讨论】:

    标签: ios swift


    【解决方案1】:

    如果ApplicationService 是您可以修改的类/结构,您可以将同步带有完成处理程序的函数调用异步函数调用,使用Swift 5.5 concurrency。代码如下所示:

    do {
      try await ApplicationService.requestAppEndPointUrl()
      try await ApplicationService.appLinkDownload()
      try await ApplicationService.requestApplicationSession()
      try await ApplicationService.validateSdk()
      try await ApplicationService.requestApplicationDetails()
    } catch {
      self.showErrorAlert(error)
    }
    

    然后,第一个错误会破坏调用链,会被咳嗽并显示出来。
    如果您必须使用同步 ApplicationService 函数,您可以使用上面引用的链接中所示的异步包装器将它们转换为异步函数。

    【讨论】:

    • 这很有帮助。感谢@Reinhard。
    【解决方案2】:

    为此,您需要使用操作队列& ** DispatchGroup** 您可以在其中进行 API 调用块操作一个操作依赖于另一个操作,它们的调度组可以帮助您保持 API 调用。

    func apiCall() {
        let dispatchGroup = DispatchGroup()
        let queue = OperationQueue()
        
        
        let operation1 = BlockOperation {
            dispatchGroup.enter()
            ApplicationService.requestAppEndPointUrl {
                Thread.sleep(forTimeInterval: Double.random(in: 1...3))
                print("ApplicationService.requestAppEndPointUrl()")
                dispatchGroup.leave()
            }
            dispatchGroup.wait()
        }
        
        let operation2 = BlockOperation {
            
            dispatchGroup.enter()
            ApplicationService.appLinkDownload {
                print("ApplicationService.appLinkDownload()")
                dispatchGroup.leave()
            }
            dispatchGroup.wait()
        }
        
        operation2.addDependency(operation1)
        
        let operation3 = BlockOperation {
            dispatchGroup.enter()
            ApplicationService.requestApplicationSession {
                Thread.sleep(forTimeInterval: Double.random(in: 1...3))
                print("ApplicationService.requestApplicationSession()")
                dispatchGroup.leave()
            }
            dispatchGroup.wait()
        }
        operation3.addDependency(operation2)
        
        let operation4 = BlockOperation {
            dispatchGroup.enter()
            ApplicationService.validateSdk {
                print("ApplicationService.validateSdk()")
                dispatchGroup.leave()
            }
            dispatchGroup.wait()
        }
        
        operation4.addDependency(operation3)
        
        let operation5 = BlockOperation {
            dispatchGroup.enter()
            ApplicationService.requestApplicationDetails {
                Thread.sleep(forTimeInterval: Double.random(in: 1...3))
                print("ApplicationService.requestApplicationDetails()")
                dispatchGroup.leave()
            }
            dispatchGroup.wait()
        }
        operation5.addDependency(operation4)
        
        queue.addOperations([operation1, operation2, operation3, operation4, operation5], waitUntilFinished: true)
    }
    

    我知道代码很少。有点讨厌,但你可以用这段代码来实现它。

    【讨论】:

    • 让先生更清楚
    【解决方案3】:

    这是一个很好的问题。因此,如果您不想将数据从一个 api 调用传递到另一个,则解决方案非常简单。

    您所要做的就是创建一个服务管理器来管理所有服务调用。

    您可以根据要调用的服务进行枚举

    enum ServiceEnum {
       case requestAppEndPointUrl
       case appLinkDownload
       case requestApplicationSession
       case validateSdk
       case requestApplicationDetails
    }
    
    enum ServiceState {
       case notStarted
       case inProgress
       case finished
       case failed
    }
    

    然后你可以做一个类的服务

    class Service {
       var service: ServiceEnum
       var serviceState: ServiceState = .notStarted
     
       init(service: ServiceEnum) {
         self.service = service
       }
    
       func updateState(serviceState: ServiceState) {
         self.serviceState = serviceState
       }
    }
    

    之后,您将需要使服务管理器

    class ServiceManager {
       private var services = [Services]()
       private var indexForService: Int {
          didSet {
              self.startServices()
          }
       }
       init() {
          services.append(.requestAppEndPointUrl)
          services.append(.appLinkDownload)
          services.append(.requestApplicationSession)
          services.append(.validateSdk)
          services.append(.requestApplicationDetails)
          indexForService = 0
       }
    
       func startServices() {
          // Check if the process has ended
          guard indexForService < services.count else {
              // If you want you can call an event here.
              // All the services have been completed
              return 
          }
          
          // Check that we have services to call
          guard services.count > 0 else {
              return
          }
    
          handleService(service: services[indexForService])
       }
    
       func haveAllFinished() -> Bool {
           return services.fist(where: { $0.serviceState == .failed || $0.serviceState == .notStarted || $0.serviceState == .inProgress }) == nil
       }
       
       func handleService(service: Service) -> Bool {
         switch(service) {
             case .requestAppEndPointUrl:
              ApplicationService.requestAppEndPointUrl { success, error in
                     let serviceState = success ? .finished : .failed
                     service.updateState(serviceState: serviceState)
                     if success {
                        self.indexForService += 1
                     } else {
                        self.showErrorAlert(error)
                     }
                 }
             // Do the same for other services
          }
       }
    } 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-02-23
      • 1970-01-01
      • 2020-08-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-29
      相关资源
      最近更新 更多