首页 > 解决方案 > 如果需要异步结果,请快速等待

问题描述

我正在学习如何使用完成处理程序和调度。有一个带有两个可选参数(groupNamegroupId)的函数。如果groupName给出,则groupId必须使用此名称检索。

如果需要该方法在继续之前完成,这是我试图等待的,但是信号量只是无限期地等待。

func getTaskId(uid: String, groupName: String?, groupId: String?, taskName: String, handler: @escaping (Array<String>?, Error?) -> Void) {
    var id: String? // this is groupId not task id *
    let semaphore = DispatchSemaphore(value: 0)
    if let groupName = groupName {
        getGroupId(uid: uid, groupName: groupName) {(groupId, groupIdErr) in
            if let err = groupIdErr {
                handler(nil, err)
                return
            } else {
                id = groupId!
                semaphore.signal()
            }
        }
    } else if let unwrappedId = groupId {
        id = unwrappedId
        semaphore.signal()
    } else {
        let err = xErrors.getTaskIdErr(message: "Failed to get group id")
        handler(nil, err)
        return
    }
    semaphore.wait()
    guard let finalId = id else {return} // groupId will be used now
    // use groupId to continue and get taskId...
}

做这样的事情的正确方法是什么?等待另一种方法的结果,但只需if要这样做。

标签: swiftasync-awaitsemaphore

解决方案


您正试图强制异步任务变为同步。不要那样做。

减少函数以仅检索 id。

func getTaskId(uid: String, groupName: String?, groupId: String?, completion: @escaping (Result<String,Error>) -> Void) {
    if let groupName = groupName {
        getGroupId(uid: uid, groupName: groupName) { groupId, groupIdErr in
            if let err = groupIdErr {
                completion(.failure(err))
            } else {
                completion(.success(groupId))
            }
        }
    } else if let unwrappedId = groupId {
        completion(.success(unwrappedId))
    } else {
       let err = xErrors.getTaskIdErr(message: "Failed to get group id")
       completion(.failure(err))
    }
}

调用它并在完成处理程序中处理 id

getTaskId(uid: "1", groupName: "foo", groupId: nil) { result in 
   switch result {
   case .success(let groupId): 
      // do something with groupId...

   case .failure(let error): print(error)
   }

}

另一种方法是声明一个函数

func doSomething(with groupId : String) {}

并更改getTaskId

func getTaskId(uid: String, groupName: String, completion: @escaping (Result<String,Error>) -> Void) {
    getGroupId(uid: uid, groupName: groupName) { groupId, groupIdErr in
        if let err = groupIdErr {
            completion(.failure(err))
        } else {
            completion(.success(groupId))
        }
    }
}

并使用它

if let groupName = groupName {
     getTaskId(uid: "1", groupName: groupName) { result in 
       switch result {
       case .success(let groupId): 
          doSomething(with : groupId)

       case .failure(let error): print(error)
       }
} else if groupId = groupId {
    doSomething(with : groupId)
}

推荐阅读