Swift"重试"逻辑请求

Lui*_*uis 12 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()
        })
    }
Run Code Online (Sandbox Code Playgroud)

Cri*_*tik 23

这是一个通用解决方案,可以应用于任何没有参数的异步函数,但回调除外.我通过只使用successfailure回调来简化逻辑,progress不应该很难添加.

所以,假设你的函数是这样的:

func startUploading(success: @escaping () -> Void, failure: @escaping (Error) -> Void) {
    DDLogDebug("JogUploader: Creating jog: \(self.jog)")

    API.sharedInstance.createJog(self.jog,
        failure: { error in
            failure(error)
        }, success: {_ in
            success()
    })
}
Run Code Online (Sandbox Code Playgroud)

retry匹配它的函数如下所示:

func retry(times: Int, task: (success: @escaping () -> Void, failure: @escaping (Error) -> Void) -> Void, success: @escaping () -> Void, failure: @escaping (Error) -> Void) {
    task(success: success, 
        failure: { error in
            // do we have retries left? if yes, call retry again
            // if not, report error
            if times > 0 {
                retry(times - 1, task: task, success: success, failure: failure)
            } else {
                failure(error)
            }
        })
}
Run Code Online (Sandbox Code Playgroud)

并且可以像这样调用:

retry(times: 3, task: startUploading,
    success: {
        print("Succeeded")
    },
    failure: { err in
        print("Failed: \(err)")
})
Run Code Online (Sandbox Code Playgroud)

startUploading如果它一直失败,上面将重试三次,否则将在第一次成功时停止.

编辑.具有其他参数的函数可以简单地嵌入到闭包中:

func updateUsername(username: String, success: @escaping () -> Void, failure: @escaping (Error) -> Void) {
    ...
}

retry(times: 3, { success, failure in updateUsername(newUsername, success, failure) },
    success: {
        print("Updated username")
    },
    failure: {
        print("Failed with error: \($0)")
    }
)
Run Code Online (Sandbox Code Playgroud)

  • @allenlinli`in` here表示闭包参数和它的主体之间的`Swift`分隔符 (2认同)

Jus*_*inM 6

这是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)
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

以下是如果您更新用​​户并想要使用更新的信息获取新用户对象,您将如何使用它:

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)
}
Run Code Online (Sandbox Code Playgroud)