Swift 使用完成处理程序和 DispatchSemaphore 的异步请求
async requests on Swift using completion handler and DispatchSemaphore
我正在尝试使用 Alamofire's
completion handler
和 DispatchSemaphores
在 Swift 上发出 async
请求。我需要得到一个响应然后 return 它到另一个方法,所以基本上这是我的代码
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
}
问题是请求总是 returns false
因为没有等到 apiRequest
响应...你有什么办法解决这个问题吗?非常感谢!
Ps。 apiRequest
returns“真”/“假”
你的 return 语句在完成处理程序之外,所以它会立即 运行,returning 它的初始 false 值,而不是 returning 的结果根据您的要求提出要求。
您应该删除响应 属性 并在完成处理程序中处理响应。
您的目的是创建一个同步函数,它将阻塞并等待异步请求完成吗?
如果是这样,您就快完成了,但是您需要将信号量更改为以 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"))")
我正在尝试使用 Alamofire's
completion handler
和 DispatchSemaphores
在 Swift 上发出 async
请求。我需要得到一个响应然后 return 它到另一个方法,所以基本上这是我的代码
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
}
问题是请求总是 returns false
因为没有等到 apiRequest
响应...你有什么办法解决这个问题吗?非常感谢!
Ps。 apiRequest
returns“真”/“假”
你的 return 语句在完成处理程序之外,所以它会立即 运行,returning 它的初始 false 值,而不是 returning 的结果根据您的要求提出要求。
您应该删除响应 属性 并在完成处理程序中处理响应。
您的目的是创建一个同步函数,它将阻塞并等待异步请求完成吗?
如果是这样,您就快完成了,但是您需要将信号量更改为以 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"))")