有没有办法通过重试做Alamofire请求

问题描述 投票:11回答:4

我在代码中有很多地方处理Alamofire请求/响应。

由于某些间歇性问题(最常见的是片状网络),这些请求中的每一个都可能失败。

我希望能够在拯救之前重试请求3次。

直截了当的方法是拥有类似的东西

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

但是,出于多种原因,我不喜欢这种方法。最明显的是我需要为每个请求类型实现这样的代码(我有15个这样的代码)。

我很好奇是否有办法做某些事情(变化很小且非侵入性)

let request = Alamofire.request(..., **3**) 
ios swift alamofire
4个回答
3
投票

使用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()之前。重试逻辑本身只有一次。


21
投票

Alamofire 4.0有一个你可以使用的RequestRetrier协议。

https://github.com/Alamofire/Alamofire/blob/master/Documentation/Alamofire%204.0%20Migration%20Guide.md#request-retrier

例:

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

4
投票

我遇到了同样的问题,我得到了使用RequestRetriershould方法和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)
    }
}

-4
投票

那么我所做的就是以下内容,如果请求失败,我会向发出请求的人发送失败的通知。然后它负责重试请求。发现这更容易。

Alamofire.request(.GET, urlString, parameters: params, headers: defaultHeaders)
        .validate()
        .responseJSON
        {
            response in

            switch response.result
            {
            case .Success:
                print("Request Successful")

                let json = JSON(data:response.data!)

                NSNotificationCenter.defaultCenter().postNotificationName(SUCCESS_NOTIFICATION, object: movieArray)

            case .Failure(let error):
                print("Request Failed with error \(error)")
                NSNotificationCenter.defaultCenter().postNotificationName(FAILURE_NOTIFICATION, object: error)
            }
    }
© www.soinside.com 2019 - 2024. All rights reserved.