斯威夫特"重试"根据要求提供逻辑

时间:2016-01-20 16:53:50

标签: swift alamofire

因此,当我的上传请求失败时,我对如何实施重试逻辑感到有点迷失。

这是我的代码,我想要一些如何做的指导

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()
        })
    }

3 个答案:

答案 0 :(得分:18)

这是一个通用解决方案,可以应用于任何没有参数的异步函数,但回调除外。我只通过successfailure回调简化了逻辑,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")