因此,当我的上传请求失败时,我对如何实施重试逻辑感到有点迷失。
这是我的代码,我想要一些如何做的指导
func startUploading(failure failure: (NSError) -> Void, success: () -> Void, progress: (Double) -> Void) {
DDLogDebug("JogUploader: Creating jog: \(self.jog)")
API.sharedInstance.createJog(self.jog,
failure: { error in
failure(error)
}, success: {_ in
success()
})
}
答案 0 :(得分:18)
这是一个通用解决方案,可以应用于任何没有参数的异步函数,但回调除外。我只通过success
和failure
回调简化了逻辑,progress
不应该难以添加。
所以,假设你的功能是这样的:
func startUploading(success: Void -> Void, failure: NSError -> Void) {
DDLogDebug("JogUploader: Creating jog: \(self.jog)")
API.sharedInstance.createJog(self.jog,
failure: { error in
failure(error)
}, success: {_ in
success()
})
}
匹配它的retry
函数如下所示:
func retry(numberOfTimes: Int, task: (success: Void -> Void, failure: NSError -> Void) -> Void, success: Void -> Void, failure: NSError -> Void) {
task(success: success,
failure: { error in
// do we have retries left? if yes, call retry again
// if not, report error
if numberOfTimes > 1 {
retry(numberOfTimes - 1, task: task, success: success, failure: failure)
} else {
failure(error)
}
})
}
可以像这样调用:
retry(3, task: startUploading,
success: {
print("Succeeded")
},
failure: { err in
print("Failed: \(err)")
})
如果失败,上述内容将重试startUploading
次呼叫三次,否则将在第一次成功时停止。
修改即可。具有其他参数的函数可以简单地嵌入到闭包中:
func updateUsername(username: String, success: Void -> Void, failure: NSError -> Void) {
...
}
retry(3, { success, failure in updateUsername(newUsername, success, failure) },
success: {
print("Updated username")
},
failure: {
print("Failed with error: \($0)")
}
)
答案 1 :(得分:5)
这是swift 3的更新答案。我还在成功块中添加了一个通用对象,因此如果在网络调用完成后创建一个对象,则可以将其传递给最终的闭包。这是重试功能:
func retry<T>(_ attempts: Int, task: @escaping (_ success: @escaping (T) -> Void, _ failure: @escaping (Error) -> Void) -> Void, success: @escaping (T) -> Void, failure: @escaping (Error) -> Void) {
task({ (obj) in
success(obj)
}) { (error) in
print("Error retry left \(attempts)")
if attempts > 1 {
self.retry(attempts - 1, task: task, success: success, failure: failure)
} else {
failure(error)
}
}
}
以下是如果您更新用户并希望使用更新的信息取回新用户对象,您将如何使用它:
NetworkManager.shared.retry(3, task: { updatedUser, failure in
NetworkManager.shared.updateUser(user, success: updatedUser, error: failure) }
, success: { (updatedUser) in
print(updatedUser.debugDescription)
}) { (err) in
print(err)
}
答案 2 :(得分:0)
已更新为swift 5,具有结果类型,而不是成功和失败块。
func retry<T>(_ attempts: Int, task: @escaping (_ completion:@escaping (Result<T, Error>) -> Void) -> Void, completion:@escaping (Result<T, Error>) -> Void) {
task({ result in
switch result {
case .success(_):
completion(result)
case .failure(let error):
print("retries left \(attempts) and error = \(error)")
if attempts > 1 {
self.retry(attempts - 1, task: task, completion: completion)
} else {
completion(result)
}
}
})
}
这是我们使用重试功能的方法:
func updateUser(userName: String) {
retry(3, task: { (result) in
startUploadingWithResult(userName: userName, completion: result)
}) { (newResult) in
switch newResult {
case .success(let str):
print("Success : \(str)")
case .failure(let error):
print(error)
}
}
}
updateUser(userName: "USER_NAME")