在 while 循环中使用完成处理程序
Using completion handlers inside while loop
如何在 while 循环中使用完成 handlers/dispatchqueue?
我有一个名为 getHub()
的方法,它是一个完成处理程序,因为我希望在完成相关值后执行代码。当用户按下按钮时,我称之为:
SetupAPI().getHub(completion: { response, error in
print("testing")
print(response)
print(error)
})
(上面的代码是下面所有代码应该结束的地方)
它调用我的 API,如果 API returns 一个我没有预料到的 error/a 值,或者如果 Almofire 无法执行请求出于某种原因,它会在 tries
变量上加一。允许的最大尝试次数为 maxTries
变量给出的 3 次。如果 tries
变量等于 maxTries
变量,则 bool timeout
设置为 true
。如果 tries
变量低于 maxTries
变量,则代码等待 timeoutInSeconds
- 即 10 秒 - 退出 while 循环之前的时间量,这应该 运行 代码再一次。
类似地,如果从我的 API 中获取数据返回了正确的值,那么 bool found
将设置为 true
。
如果这些变量中的任何一个为真,则 while 循环中断。并将错误发送回上述代码的完成处理程序(然后允许我告诉用户出了点问题)。
然而,当我 运行 它时,上面的完成处理程序没有完成,代码只是 运行s 通过 while 循环并一遍又一遍地调用函数,因为我的控制台充满了starting
和 fetching
通过我的两个打印语句在下面的代码中进行调试。有什么问题,我可以在这种情况下使用 DispatchQueue/ 完成处理程序吗?
通过上述代码调用的函数:
func getHub(completion: @escaping (Bool, Error?) -> Void) {
var tries = 0
let maxTries = 3
let timeoutInSeconds = 10.0
var found = false
var timeout = false
while !found || !timeout{
print("starting")
getHubCallAPI(completion: {status, error in
if(error == nil){
print(status)
if (status == "No documents found"){
if(tries >= maxTries){
print("Tired too many times")
timeout = true
return completion(false, nil)
}
tries += 1
DispatchQueue.main.asyncAfter(deadline: .now() + timeoutInSeconds){
return
}
}else{
found = true
print("Hub found")
return completion(true, nil)
}
}else{
print("error")
return completion(false, error)
}
})
}
}
函数调用 API 和 returns 它回到上面的函数 ^^:
func getHubCallAPI(completion: @escaping (String, Error?) -> Void) {
print("fetching")
AF.request("https://discovery.ellisn.com", encoding: URLEncoding.default).response { response in
print("Request: \(response.request)")
print("Response: \(response.response)")
print("Error: \(response.error)")
if(response.error != nil){
return completion("", response.error)
}
if let data = response.data, let status = String(data: data, encoding: .utf8) {
return completion(status, nil)
}
}
}
如有任何问题或需要更多说明,请尽管提问。谢谢。
您可以尝试以下方法:
func getHub(triesLeft: Int = 3, completion: @escaping (Bool, Error?) -> Void) {
let timeoutInSeconds = 1.0
print("starting")
getHubCallAPI(completion: { status, error in
if error == nil {
print(status)
if status != "No documents found" {
print("Hub found")
return completion(true, nil)
}
} else {
print("error")
return completion(false, error) // comment out if the loop should continue on error
}
if triesLeft <= 1 {
print("Tried too many times")
return completion(false, nil)
}
DispatchQueue.main.asyncAfter(deadline: .now() + timeoutInSeconds) {
getHub(triesLeft: triesLeft - 1, completion: completion)
}
})
}
然后像这样调用一次:
getHub(triesLeft: 2, completion: { ... })
请注意,除非您出于其他原因需要它,否则没有必要 return (Bool, Error?)
。第二个参数总是 nil
- 你可能想要传播你的错误。理论上你可以 return (String?, Error?)
.
如何在 while 循环中使用完成 handlers/dispatchqueue?
我有一个名为 getHub()
的方法,它是一个完成处理程序,因为我希望在完成相关值后执行代码。当用户按下按钮时,我称之为:
SetupAPI().getHub(completion: { response, error in
print("testing")
print(response)
print(error)
})
(上面的代码是下面所有代码应该结束的地方)
它调用我的 API,如果 API returns 一个我没有预料到的 error/a 值,或者如果 Almofire 无法执行请求出于某种原因,它会在 tries
变量上加一。允许的最大尝试次数为 maxTries
变量给出的 3 次。如果 tries
变量等于 maxTries
变量,则 bool timeout
设置为 true
。如果 tries
变量低于 maxTries
变量,则代码等待 timeoutInSeconds
- 即 10 秒 - 退出 while 循环之前的时间量,这应该 运行 代码再一次。
类似地,如果从我的 API 中获取数据返回了正确的值,那么 bool found
将设置为 true
。
如果这些变量中的任何一个为真,则 while 循环中断。并将错误发送回上述代码的完成处理程序(然后允许我告诉用户出了点问题)。
然而,当我 运行 它时,上面的完成处理程序没有完成,代码只是 运行s 通过 while 循环并一遍又一遍地调用函数,因为我的控制台充满了starting
和 fetching
通过我的两个打印语句在下面的代码中进行调试。有什么问题,我可以在这种情况下使用 DispatchQueue/ 完成处理程序吗?
通过上述代码调用的函数:
func getHub(completion: @escaping (Bool, Error?) -> Void) {
var tries = 0
let maxTries = 3
let timeoutInSeconds = 10.0
var found = false
var timeout = false
while !found || !timeout{
print("starting")
getHubCallAPI(completion: {status, error in
if(error == nil){
print(status)
if (status == "No documents found"){
if(tries >= maxTries){
print("Tired too many times")
timeout = true
return completion(false, nil)
}
tries += 1
DispatchQueue.main.asyncAfter(deadline: .now() + timeoutInSeconds){
return
}
}else{
found = true
print("Hub found")
return completion(true, nil)
}
}else{
print("error")
return completion(false, error)
}
})
}
}
函数调用 API 和 returns 它回到上面的函数 ^^:
func getHubCallAPI(completion: @escaping (String, Error?) -> Void) {
print("fetching")
AF.request("https://discovery.ellisn.com", encoding: URLEncoding.default).response { response in
print("Request: \(response.request)")
print("Response: \(response.response)")
print("Error: \(response.error)")
if(response.error != nil){
return completion("", response.error)
}
if let data = response.data, let status = String(data: data, encoding: .utf8) {
return completion(status, nil)
}
}
}
如有任何问题或需要更多说明,请尽管提问。谢谢。
您可以尝试以下方法:
func getHub(triesLeft: Int = 3, completion: @escaping (Bool, Error?) -> Void) {
let timeoutInSeconds = 1.0
print("starting")
getHubCallAPI(completion: { status, error in
if error == nil {
print(status)
if status != "No documents found" {
print("Hub found")
return completion(true, nil)
}
} else {
print("error")
return completion(false, error) // comment out if the loop should continue on error
}
if triesLeft <= 1 {
print("Tried too many times")
return completion(false, nil)
}
DispatchQueue.main.asyncAfter(deadline: .now() + timeoutInSeconds) {
getHub(triesLeft: triesLeft - 1, completion: completion)
}
})
}
然后像这样调用一次:
getHub(triesLeft: 2, completion: { ... })
请注意,除非您出于其他原因需要它,否则没有必要 return (Bool, Error?)
。第二个参数总是 nil
- 你可能想要传播你的错误。理论上你可以 return (String?, Error?)
.