Alamofire源码学习目录合集swift
RequestInterceptor请求拦截器是一个协议,用来在请求流程中拦截请求,并对请求进行一些必要的处理,这是一个组合协议:RequestAdapter请求适配器与RequestRetrier请求重试器。使用者能够本身实现请求拦截器,根据本身的需求适配URLRequest,或者定义本身的重试逻辑,也可使用Alamofire默认实现的简易适配器,设置组合协议我的以为是由于,RequestAdapter是对请求的拦截预处理,RequestRetrier是对响应重试的拦截预处理,恰好请求响应一对,组合起来做为统一的一个对象来在生成Request时传入使用。api
只有一个方法,用来在Request建立好初始的URLRequest后,对URLRequest进行适配,适配处理先后均会告诉监听器对应的通知。数组
/// 入参为初始URLRequest, Session以及适配完成后的回调, 回调参数为Result对象, 能够为成功适配后的URLRequest对象, 也能够返回错误, 会向上抛出从建立requestAdaptationFailed错误
func adapt(_ urlRequest: URLRequest, for session: Session, completion: @escaping (Result<URLRequest, Error>) -> Void)
复制代码
也是只有一个方法,用来在请求失败时,决定是直接抛出错误,仍是依据必定的逻辑进行重试:markdown
// 参数为: Request对象, Session, 请求失败的错误信息以及重试逻辑回调, 回调参数为重试逻辑, 调用者根据该逻辑决定重试行为
func retry(_ request: Request, for session: Session, dueTo error: Error, completion: @escaping (RetryResult) -> Void)
复制代码
定义了四个重试逻辑session
public enum RetryResult {
/// 马上重试
case retry
/// 延迟重试
case retryWithDelay(TimeInterval)
/// 不重试,直接完成请求
case doNotRetry
/// 不重试并抛出错误
case doNotRetryWithError(Error)
}
//扩展一下快速取得相关信息, 两个可选值属性方便快速作出判断
extension RetryResult {
/// 是否须要重试
var retryRequired: Bool {
switch self {
case .retry, .retryWithDelay: return true
default: return false
}
}
/// 延迟重试时间
var delay: TimeInterval? {
switch self {
case let .retryWithDelay(delay): return delay
default: return nil
}
}
/// 不重试并抛出错误时的错误信息
var error: Error? {
guard case let .doNotRetryWithError(error) = self else { return nil }
return error
}
}
复制代码
直接把两个协议组合在一块儿供外部实现闭包
public protocol RequestInterceptor: RequestAdapter, RequestRetrier {}
//扩展一下,使得即使遵循协议也能够不实现方法,依旧不会报错
extension RequestInterceptor {
public func adapt(_ urlRequest: URLRequest, for session: Session, completion: @escaping (Result<URLRequest, Error>) -> Void) {
//直接返回原请求
completion(.success(urlRequest))
}
public func retry(_ request: Request, for session: Session, dueTo error: Error, completion: @escaping (RetryResult) -> Void) {
//不重试
completion(.doNotRetry)
}
}
复制代码
Alamofire预先定义了一些简易的拦截器,能够直接使用,也能够根据本身需求自行实现post
// 先定义了一个用来适配请求的闭包:
public typealias AdaptHandler = (URLRequest, Session, _ completion: @escaping (Result<URLRequest, Error>) -> Void) -> Void
//而后实现基于闭包的请求适配器,只是简单的持有一个闭包来适配请求:
open class Adapter: RequestInterceptor {
private let adaptHandler: AdaptHandler
public init(_ adaptHandler: @escaping AdaptHandler) {
self.adaptHandler = adaptHandler
}
open func adapt(_ urlRequest: URLRequest, for session: Session, completion: @escaping (Result<URLRequest, Error>) -> Void) {
adaptHandler(urlRequest, session, completion)
}
}
复制代码
//先定义了一个用来决定重试逻辑的闭包:
public typealias RetryHandler = (Request, Session, Error, _ completion: @escaping (RetryResult) -> Void) -> Void
//而后实现基于闭包的重试器:
open class Retrier: RequestInterceptor {
private let retryHandler: RetryHandler
public init(_ retryHandler: @escaping RetryHandler) {
self.retryHandler = retryHandler
}
open func retry(_ request: Request, for session: Session, dueTo error: Error, completion: @escaping (RetryResult) -> Void) {
retryHandler(request, session, error, completion)
}
}
复制代码
持有两个数组,一个保存适配器对象,一个保存重试器对象,而后重试的时候,挨个去处理,所以要注意传入时的顺序问题学习
open class Interceptor: RequestInterceptor {
/// 保存适配器, 有任何一个出现错误, 就会抛出错误
public let adapters: [RequestAdapter]
/// All `RequestRetrier`s associated with the instance. These retriers will be run one at a time until one triggers retry.
/// 保存重试器, 有任何一个出现了须要重试(当即重试或者延迟重试)就会中止, 而后抛出须要重试. 有任何一个不重试并抛出错误也会中止, 并抛出错误.
public let retriers: [RequestRetrier]
/// 也可使用重试器与适配器回调来建立单个的组合器
public init(adaptHandler: @escaping AdaptHandler, retryHandler: @escaping RetryHandler) {
adapters = [Adapter(adaptHandler)]
retriers = [Retrier(retryHandler)]
}
/// 用两个数组初始化
public init(adapter: RequestAdapter, retrier: RequestRetrier) {
adapters = [adapter]
retriers = [retrier]
}
/// 用适配器+重试器+拦截器数组初始化, 会把拦截器数组均加入到适配器与重试器数组中
public init(adapters: [RequestAdapter] = [], retriers: [RequestRetrier] = [], interceptors: [RequestInterceptor] = []) {
self.adapters = adapters + interceptors
self.retriers = retriers + interceptors
}
/// 适配器代理方法, 调下面的私有方法
open func adapt(_ urlRequest: URLRequest, for session: Session, completion: @escaping (Result<URLRequest, Error>) -> Void) {
adapt(urlRequest, for: session, using: adapters, completion: completion)
}
/// 私有适配方法, 会不停递归
private func adapt(_ urlRequest: URLRequest, for session: Session, using adapters: [RequestAdapter], completion: @escaping (Result<URLRequest, Error>) -> Void) {
// 用来准备递归的数组
var pendingAdapters = adapters
// 递归空了就执行回调并返回
guard !pendingAdapters.isEmpty else { completion(.success(urlRequest)); return }
// 取出第一个适配器
let adapter = pendingAdapters.removeFirst()
// 走你
adapter.adapt(urlRequest, for: session) { result in
switch result {
case let .success(urlRequest):
// 适配经过, 递归去适配剩下的
self.adapt(urlRequest, for: session, using: pendingAdapters, completion: completion)
case .failure:
// 适配失败, 直接抛出错误
completion(result)
}
}
}
// 重试器逻辑, 调下面私有方法
open func retry(_ request: Request, for session: Session, dueTo error: Error, completion: @escaping (RetryResult) -> Void) {
retry(request, for: session, dueTo: error, using: retriers, completion: completion)
}
// 私有重试逻辑, 会递归调用
private func retry(_ request: Request, for session: Session, dueTo error: Error, using retriers: [RequestRetrier], completion: @escaping (RetryResult) -> Void) {
// 用来递归的重试器数组
var pendingRetriers = retriers
// 递归完成且没有触发重试或错误, 就返回不重试, 并返回不重试
guard !pendingRetriers.isEmpty else { completion(.doNotRetry); return }
// 取出第一个
let retrier = pendingRetriers.removeFirst()
// 走你
retrier.retry(request, for: session, dueTo: error) { result in
switch result {
case .retry, .retryWithDelay, .doNotRetryWithError:
// 重试, 延迟重试, 不重试并抛出错误的话, 执行回调
completion(result)
case .doNotRetry:
// 不然开始递归
self.retry(request, for: session, dueTo: error, using: pendingRetriers, completion: completion)
}
}
}
}
复制代码
以上纯属我的理解,不免有错误,若是发现有错,欢迎评论指出~~将第一时间改正,也欢迎评论讨论,很是感谢~~ui