Ios 有没有办法通过重试来执行Alamofire请求
我在代码中有很多地方处理Alamofire请求/响应 每个请求都可能由于某些间歇性问题而失败(最常见的是网络故障) 我希望能够在退出之前重试请求3次 最简单的方法就是拥有这样的东西Ios 有没有办法通过重试来执行Alamofire请求,ios,swift,alamofire,Ios,Swift,Alamofire,我在代码中有很多地方处理Alamofire请求/响应 每个请求都可能由于某些间歇性问题而失败(最常见的是网络故障) 我希望能够在退出之前重试请求3次 最简单的方法就是拥有这样的东西 var errorCount = 0 func requestType1() { let request = Alamofire.request(...).responseJSON { response in if (isError(response) && errorCount
var errorCount = 0
func requestType1() {
let request = Alamofire.request(...).responseJSON { response in
if (isError(response) && errorCount < 3) {
errorCount += 1
request1()
}
if (isError(response)) {
handleError()
}
handleSuccess()
}
}
Swift的语法优势之一是你可以使用:
public func updateEvents(someNormalParam: Bool = true, someBlock: (Void->Void))
像这样:
updateEvents(someNormalParam: false) {...}
注意,该块位于updateEvents函数()的外部,与您通常期望的相反。只有当块是函数声明中的最后一项时,它才起作用
这意味着,如果您碰巧有一个块,比如Alamofire请求,您可以使用重试功能有效地将其包装起来。一个稍微复杂的问题是要调用块中的块。没什么大不了的:
func retryWrapper(alamoBlock: (Void->Request)) {
alamoblock().responseJSON() {
//Your retry logic here
}
}
你这样使用它:
retryWrapper() {
Alamofire.request(method, targetUrl, parameters: parameters, encoding: encoding)
}
这意味着您所要做的就是找到Alamofire调用并将它们包装在{}中,然后将retryWrapper()放在前面。重试逻辑本身只存在一次。Alamofire 4.0有一个可以使用的
RequestRetrier
协议
例如:
class OAuth2Handler: RequestAdapter, RequestRetrier {
public func should(_ manager: SessionManager, retry request: Request, with error: Error, completion: RequestRetryCompletion) {
if let response = request.task.response as? HTTPURLResponse, response.statusCode == 401 {
completion(true, 1.0) // retry after 1 second
} else {
completion(false, 0.0) // don't retry
}
// Or do something with the retryCount
// i.e. completion(request.retryCount <= 10, 1.0)
}
}
let sessionManager = SessionManager()
sessionManager.retrier = OAuth2Handler()
sessionManager.request(urlString).responseJSON { response in
debugPrint(response)
}
类OAuth2Handler:RequestAdapter、RequestRetrier{
public func应该(manager:SessionManager,重试请求:request,错误:error,完成:RequestRetryCompletion){
如果让response=request.task.response为?HTTPURLResponse,则response.statusCode==401{
完成(true,1.0)//1秒后重试
}否则{
完成(false,0.0)//不重试
}
//或者用retryCount做点什么
//例如,完成(request.retryCount我也遇到了同样的问题,我使用
RequestRetrier
、should
方法和request.retryCount
获得了要重试的请求。类似的情况:
// MARK: - RequestRetry
public func should(_ manager: SessionManager, retry request: Request, with error: Error, completion: @escaping RequestRetryCompletion) {
lock.lock() ; defer { lock.unlock() }
if let response = request.task?.response as? HTTPURLResponse{
if response.statusCode == 401 {
requestsToRetry.append(completion)
getToken { (expires, _) in
_ = SessionCountdownToken.sharedInstance.startCount(expirationTime: expires)
}
} else {
if request.retryCount == 3 { completion(false, 0.0 ); return}
completion(true, 1.0)
return
}
} else {
completion(false, 0.0)
}
}
我已经为请求检索器创建了一个包装类。 并使用请求所需的会话管理器中的请求检索器
static let sharedManager: SessionManager = {
let configuration = URLSessionConfiguration.default
let manager = Alamofire.SessionManager(configuration: configuration)
let requestRet = NetworkRequestRetrier()
manager.retrier = requestRet
return manager
}()
你能制作一个将请求作为结束块的包装器吗?这样,你就不用直接调用请求,而是在块中有相同的请求代码,但调用包装器?这样更容易更改代码。卡洛斯。我认为你是对的。我忽略了这一点:).你想写下来作为回答吗?当然,给我一点时间,我会写的that@VictorRonin你能解释一下你是怎么得到它的吗?我有点困惑我们的反应是什么这里?我有点生疏,但它看起来像是块返回一个请求,它有一个函数将其转换为JSONCant我们使用requestRetrier?不知道。自从我写这篇文章以来,事情可能已经开始了。我正在使用Alamofire.Request…方法,以及我如何适应requestRetrier?现在我使用APIRouter和UrlRequestConverable方法,AF.request(request).validate().responseJSON{(response)……我正在设置APIRouter中的标头……使用Retrier..看起来我需要改变我的整个方法?或者有没有简单的方法来使用Retrier并将影响降到最低..我使用这种方法@anoop4real请向其他人提出一个新的问题,以便向你提供建议,以便评论与此答案相关第一行的锁是什么?@jayantrawat我猜它是一个
NSRecursiveLock()
实例
static let sharedManager: SessionManager = {
let configuration = URLSessionConfiguration.default
let manager = Alamofire.SessionManager(configuration: configuration)
let requestRet = NetworkRequestRetrier()
manager.retrier = requestRet
return manager
}()