【问题标题】:async requests on Swift using completion handler and DispatchSemaphoreSwift 上使用完成处理程序和 DispatchSemaphore 的异步请求
【发布时间】:2021-01-06 01:16:30
【问题描述】:

我正在尝试使用 Alamofire's completion handlerDispatchSemaphores 在 Swift 上发出 async 请求。我需要得到响应,然后将其返回给另一个方法,所以基本上这是我的代码

func customRequest(zipCode: String) -> Bool{
    var response = false

    let dispatchQueueProcess = DispatchQueue.global(qos: .userInitiated)
    let semaphore = DispatchSemaphore(value: 1)
    
    dispatchQueueProcess.async {
        
        semaphore.wait()

        apiRequest(zipCode: zipCode) { apiResponse in
        
            if apiResponse != nil {
            
response = apiResponse
               
             
            } else {
                print("Server did not Response")
            }
            
            semaphore.signal()
            
            
        }
    }
    
    return response
}

问题是请求总是返回false,因为没有等到apiRequest 响应......你有什么想法来解决这个问题吗?非常感谢!

附言。 apiRequest 返回“真”/“假”

【问题讨论】:

    标签: swift signals dispatchsemaphore


    【解决方案1】:

    您是否打算在这里创建一个同步函数,该函数将阻塞并等待异步请求完成?

    如果是这样,您就快到了,但您需要将 Semaphore 更改为从 0 而不是 1 开始(从 1 递减到 0 不会停止执行,它需要变为负数),并且您需要移动wait() 在闭包之外调用,否则你不会阻止函数返回,而是会阻止你的闭包完成。

    func customRequest(zipCode: String) -> Bool {
        var response = false
        
        let dispatchQueueProcess = DispatchQueue.global(qos: .userInitiated)
        let semaphore = DispatchSemaphore(value: 0)
        
        // Start async work on background thread, current function's thread 
        // execution point will then immediately move to the line 
        // after the closing brace 
        dispatchQueueProcess.async {
            apiRequest(zipCode: zipCode) { apiResponse in
                if let apiResponse = apiResponse {
                    response = apiResponse
                } else {
                    print("Server did not Response")
                }
    
                // Tell the original function's thread that it is OK to continue
                semaphore.signal()
    
            }
        }
    
        // Immediately wait for the semaphore after starting the async work so that
        // the customRequest(zipCode:) function pauses here until the semaphore is
        // signalled in the closure.
        semaphore.wait()
        
        // Once the semaphore.signal() call happens in the async closure execution
        // resumes, and the response variable can now be returned with the updated
        // value.
        return response
    }
    

    您可能会发现您实际上并不想创建这样的同步函数,因为如果您从主队列中调用它,您将冻结 UI,直到收到响应。

    编辑:此示例应在 Playground 中复制粘贴运行

    import Foundation
    
    // template function to simulate the API call
    func apiRequest(zipCode: String, response: (Bool?)->Void) {
        sleep(3)
        response(true)
    }
    
    func customRequest(zipCode: String) -> Bool{
        var response = false
        
        let dispatchQueueProcess = DispatchQueue.global(qos: .userInitiated)
        let semaphore = DispatchSemaphore(value: 0)
        
        dispatchQueueProcess.async {
            apiRequest(zipCode: zipCode) { apiResponse in
                if let apiResponse = apiResponse {
                    response = apiResponse
                } else {
                    print("Server did not Response")
                }
                semaphore.signal()
    
            }
        }
        
        semaphore.wait()
        
        return response
    }
    
    print("Result: \(customRequest(zipCode: "90030"))")
    

    【讨论】:

    • 这正是我要找的!让我明天在工作中尝试,如果您的解决方案有效,我会告诉您,希望会发生。非常感谢!
    • 没用老兄,唯一发生的就是卡屏,所以我试试 Flanker 说的
    • 当您说“冻结屏幕”时,您是什么意思?你的意思是当你调用这个函数时UI被锁定了?如果是这样,如果您的目标确实是围绕调用创建一个阻塞包装器,那将是可以预料的。当我在操场上运行它时,它会按描述工作。更新了上面的示例,您可以直接将其复制粘贴到 Playground 中。
    • 我的意思是,API 进程只有在我使用完成处理程序而不是返回示例时才响应
    【解决方案2】:

    您的 return 语句在完成处理程序之外,因此它将立即运行,返回它的初始 false 值,而不是按照您的要求返回请求的结果。

    您应该删除响应属性并在完成处理程序中处理响应。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-07-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-25
      • 2019-01-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多