Alamofire4.0的封裝,實(shí)現(xiàn)請求失敗后的重連策略

協(xié)議介紹

主要使用了Alamofire4.0新增的兩個(gè)協(xié)議RequestRetrier和RequestAdapter.

  • RequestRetrier(請求重連)
public typealias RequestRetryCompletion = (_ shouldRetry: Bool, _ timeDelay: TimeInterval) -> Void

public protocol RequestRetrier {
    func should(_ manager: SessionManager, retry request: Request, with error: Error, completion: @escaping RequestRetryCompletion)
}

它可以在Request 遇到 Error 的時(shí)候, 在指定的延遲之后重新發(fā)起請求.

注意事項(xiàng):為了避免無限重連,需要對請求地址做最大重連限制

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) // 1秒后重試
        } else {
            completion(false, 0.0) // 不重連
        }
    }
}

let sessionManager = SessionManager()
sessionManager.retrier = OAuth2Handler()

sessionManager.request(urlString).responseJSON { response in
    debugPrint(response)
}
  • RequestAdapter(請求適配器)
public protocol RequestAdapter {
    func adapt(_ urlRequest: URLRequest) throws -> URLRequest
}

它可以讓每一個(gè) SessionManager 生成的 Request 都在生成之前被解析并且按照規(guī)則適配. 一個(gè)使用適配器很典型的場景就是給請求添加一個(gè) Authorization 的請求頭.

class AccessTokenAdapter: RequestAdapter {
    private let accessToken: String

    init(accessToken: String) {
        self.accessToken = accessToken
    }

    func adapt(_ urlRequest: URLRequest) throws -> URLRequest {
        var urlRequest = urlRequest

        if urlRequest.urlString.hasPrefix("https://httpbin.org") {
            urlRequest.setValue("Bearer " + accessToken, forHTTPHeaderField: "Authorization")
        }

        return urlRequest
    }
}

let sessionManager = SessionManager()
sessionManager.adapter = AccessTokenAdapter(accessToken: "1234")

sessionManager.request("https://httpbin.org/get")

如果一個(gè) Error 在適配過程中產(chǎn)生的話, 它會逐層拋出, 最后傳遞到 Request 的請求回調(diào)里.

封裝HTTPSessionManager

注意事項(xiàng):RequestRetrier協(xié)議的回調(diào)是請求失敗后才會進(jìn)入,如果是請求成功后,需要對個(gè)別錯(cuò)誤碼進(jìn)行重連操作,可以參考validate

import Alamofire
import SwiftyJSON

/// 數(shù)據(jù)回調(diào)
public typealias HTTPSuccessBlock = (_ result : JSON) -> Void
public typealias HTTPFailureBlock = (_ error : HTTPErrorCode) -> Void


public enum HTTPErrorCode : Int, Error {
    case SystemError       = 4000        //參數(shù)錯(cuò)誤
    case UnknownError       = 5000        //未知錯(cuò)誤
    .
    .
    .
}


class HTTPSessionManager: NSObject {

    /// Alamofire
    private var manager : SessionManager {
        let manager = SessionManager.default
        manager.retrier = OAuth2Handler()
        manager.adapter = OAuth2Handler()
        return manager
    }
}

extension HTTPSessionManager {
    
    public func request(methodType : HTTPMethod, urlString : String, parameters : [String: Any]?, successBlock : @escaping HTTPSuccessBlock, failureBlock : @escaping HTTPFailureBlock) {
        
        manager.request(urlString, method: methodType, parameters: requestJson, encoding: JSONEncoding.default, headers: SessionManager.defaultHTTPHeaders)
            .responseJSON { (json) in
                // 返回?cái)?shù)據(jù)處理
                switch json.result {
                case .success(let result):
                    let retCode = JSON(result)["retCode"].intValue
                    if retCode == 成功 {
                        successBlock(JSON(result))
                    } else {
                        guard let errorCode = HTTPErrorCode(rawValue: retCode) else {
                            return failureBlock(HTTPErrorCode.UnknownError)
                        }
                        return failureBlock(errorCode)
                    }
                case .failure(let error):
                    failureBlock(HTTPErrorCode.UnknownError)
                }
        }
    }   
}

參考:
Alamofire4.0 遷移指南

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容