Alamofire源码分析 - POST请求

本文基于Alamofire v5.6.1,主要通过一个POST请求看看Alamofire源码是如何实现该过程的。请求代码如下:

let url = "xxxxxxxxxxxxxxxxxxxx"
let hs = headers.map { HTTPHeader(name: $0, value: $1) }
        var httpHeaders: HTTPHeaders = HTTPHeaders(hs)
        httpHeaders.add(HTTPHeader(name: "sessionToken", value: "xxxxxxxxx"))
        
        AF.request(url, method: .post, parameters: parameters, encoding: JSONEncoding.default, headers: httpHeaders).response { response in }

初始化Session

首先点进AF,发现其代表的就是Session类的单利

public let AF = Session.default

open class Session {
    public static let `default` = Session()
}

接着看下Session是如何初始化的,为了简化代码,暂时删除了一些为nil的参数,这些后面再解释


public convenience init(configuration: URLSessionConfiguration = URLSessionConfiguration.af.default,
                            delegate: SessionDelegate = SessionDelegate(),
                            rootQueue: DispatchQueue = DispatchQueue(label: "org.alamofire.session.rootQueue"),
                            startRequestsImmediately: Bool = true,
                            eventMonitors: [EventMonitor] = []) {
        // Alamofire 不支持后台任务
        precondition(configuration.identifier == nil, "Alamofire does not support background URLSessionConfigurations.")

        // 保证rootQueue传进来为主队列或默认创建的串行队列
        let serialRootQueue = (rootQueue === DispatchQueue.main) ? rootQueue : DispatchQueue(label: rootQueue.label,
                                                                                             target: rootQueue)
        // 初始化URLSession,设置delegate为SessionDelegate类                                                                                     
        let delegateQueue = OperationQueue(maxConcurrentOperationCount: 1, underlyingQueue: serialRootQueue, name: "\(serialRootQueue.label).sessionDelegate")
        let session = URLSession(configuration: configuration, delegate: delegate, delegateQueue: delegateQueue)

        self.init(xxx)
    }

首先调用Session的便捷初始化方法,保证了rootQueue的安全,然后设置了URLSession的delegate为SessionDelegate类,说明URLSession请求过程的回调就是通过SessionDelegate类来接受的,这个可以点进去查看相关请求回调,这个后面再讲。

接下来进入Sessiond的必要初始化方法看看

public init(session: URLSession,
                delegate: SessionDelegate,
                rootQueue: DispatchQueue,
                startRequestsImmediately: Bool = true,
                requestQueue: DispatchQueue? = nil,
                serializationQueue: DispatchQueue? = nil,
                eventMonitors: [EventMonitor] = []) {
        precondition(session.configuration.identifier == nil,
                     "Alamofire does not support background URLSessionConfigurations.")
        precondition(session.delegateQueue.underlyingQueue === rootQueue,
                     "Session(session:) initializer must be passed the DispatchQueue used as the delegateQueue's underlyingQueue as rootQueue.")

        self.session = session
        self.delegate = delegate
        self.rootQueue = rootQueue
        self.startRequestsImmediately = startRequestsImmediately
        // requestQueue和serializationQueue都是基于rootQueue的串行队列
        self.requestQueue = requestQueue ?? DispatchQueue(label: "\(rootQueue.label).requestQueue", target: rootQueue)
        self.serializationQueue = serializationQueue ?? DispatchQueue(label: "\(rootQueue.label).serializationQueue", target: rootQueue)
        // 初始化CompositeEventMonitor对象(默认的监听器 + 传入的事件监听器)
        eventMonitor = CompositeEventMonitor(monitors: defaultEventMonitors + eventMonitors)
        delegate.eventMonitor = eventMonitor
        delegate.stateProvider = self
    }

上面初始化方法中,主要是设置对一些参数的设置,其中重点看SessionDelegate的两个协议eventMonitor和stateProvider,eventMonitor协议方法调用方法时机就是在URLSession的请求过程代理方法中,从而对请求过程中的事件进行监听。而stateProvider协议也是差不多,提供多种请求状态回调,其实现是在Session类中(这些等请求任务发出后再详细讲解做了什么事)。

初始化DataRequest

接下来回到Session的reqeust(...)方法中(没传的暂时省略)

open func request(_ convertible: URLConvertible,
                      method: HTTPMethod = .get,
                      parameters: Parameters? = nil,
                      encoding: ParameterEncoding = URLEncoding.default,
                      headers: HTTPHeaders? = nil) -> DataRequest {
        let convertible = RequestConvertible(url: convertible,
                                             method: method,
                                             parameters: parameters,
                                             encoding: encoding,
                                             headers: headers,)

        return request(convertible, interceptor: interceptor)
    }

首先看参数,URLConvertible是用来构造URL的,遵守该协议的类都会通过asURL()方法被转换成URL

public protocol URLConvertible {
    func asURL() throws -> URL
}

HTTPMethod参数用来表示HTTP方法,该结构体遵守RawRepresentable协议,因此可以通过rawValue进行初始化,且rawValue是唯一的

public struct HTTPMethod: RawRepresentable, Equatable, Hashable {
    public static let connect = HTTPMethod(rawValue: "CONNECT")
    ...
    public let rawValue: String
    public init(rawValue: String) {
        self.rawValue = rawValue
    }
}

Parameters参数则只是对字典的重新定义

public typealias Parameters = [String: Any]

ParameterEncoding参数则是对parameters参数编码的协议,具体实现在JSONEncoding和URLEncoding两个类中,其中JSONEncoding是将parameters放请求体里,而URLEncoding是将parameters拼接在url后面或者放请求体里(这两个类的编码实现后面再详细说)

参数讲解完了,接下来回到request(...)方法中。可以看到根据request(...)传入的参数,构造了一个RequestConvertible结构体,点进去看对应的实现:

public protocol URLRequestConvertible {
    func asURLRequest() throws -> URLRequest
}

extension URLRequestConvertible {
    public var urlRequest: URLRequest? { try? asURLRequest() }
}

struct RequestConvertible: URLRequestConvertible {
        let url: URLConvertible
        let method: HTTPMethod
        let parameters: Parameters?
        let encoding: ParameterEncoding
        let headers: HTTPHeaders?
        let requestModifier: RequestModifier?

        func asURLRequest() throws -> URLRequest {
            var request = try URLRequest(url: url, method: method, headers: headers)
            try requestModifier?(&request)

            return try encoding.encode(request, with: parameters)
        }
    }

该类遵守URLRequestConvertible协议,这个协议是为了安全的构造URLRequest,RequestConvertible的作用就是为了构造URLRequest,至于RequestConvertible里面的asURLRequest()实现方法等调用时再回过头来看

接下来进入到request(_ convertible: URLRequestConvertible, interceptor: RequestInterceptor? = nil)方法中:

open func request(_ convertible: URLRequestConvertible, interceptor: RequestInterceptor? = nil) -> DataRequest {
        let request = DataRequest(convertible: convertible,
                                  underlyingQueue: rootQueue,
                                  serializationQueue: serializationQueue,
                                  eventMonitor: eventMonitor,
                                  interceptor: interceptor,
                                  delegate: self)

        perform(request)

        return request
    }

该方法首先是生成DataRequest对象,该对象的父类是Reqeust。Reqeust类的作用是提供所有的请求数据,请求状态、请求回调等。该类有四个子类分别是处理相对应的请求,例如普通请求、流式请求、上传、下载,当前主要针对普通请求分析,其他的单独开篇讲解

接下来进入到perform()方法中:

func perform(_ request: Request) {
        rootQueue.async {
            // 默认request.state为.initialized
            guard !request.isCancelled else { return }

            // activeRequests保存所有进行中的请求
            self.activeRequests.insert(request)

            self.requestQueue.async {
                // 需要注意的点:由于UploadRequest继承自DataRequest,因此需要放在第一个,否则会被转换成DataRequest
                switch request {
                case let r as UploadRequest: self.performUploadRequest(r)
                case let r as DataRequest: self.performDataRequest(r)
                case let r as DownloadRequest: self.performDownloadRequest(r)
                case let r as DataStreamRequest: self.performDataStreamRequest(r)
                default: fatalError("Attempted to perform unsupported Request subclass: \(type(of: request))")
                }
            }
        }
    }

该方法中,首先是将request保存在activeRequests属性中,该属性保存着正在进行中的请求,而且会在请求响应结束后清除。

创建URLRequest

接着就是调用performDataRequest()performSetupOperations()方法

func performDataRequest(_ request: DataRequest) {
        // 确保当前线程为requestQueue(其实performSetupOperations方法内部也有该判断, 感觉这个判断的条件好像没什么意义)
        dispatchPrecondition(condition: .onQueue(requestQueue))

        performSetupOperations(for: request, convertible: request.convertible)
    }
func performSetupOperations(for request: Request,
                                convertible: URLRequestConvertible,
                                shouldCreateTask: @escaping () -> Bool = { true }) {
        dispatchPrecondition(condition: .onQueue(requestQueue))

        let initialRequest: URLRequest

        do {
            // 调用RequestConvertible的asURLRequest方法, 拿到URLRequest对象
            initialRequest = try convertible.asURLRequest()
            // 保证请求有效
            try initialRequest.validate()
        } catch {
            rootQueue.async { request.didFailToCreateURLRequest(with: error.asAFError(or: .createURLRequestFailed(error: error))) }
            return
        }
		// 保存request
        rootQueue.async { request.didCreateInitialURLRequest(initialRequest) }

        guard !request.isCancelled else { return }

        // 默认没有设置拦截器
        guard let adapter = adapter(for: request) else {
            // shouldCreateTask默认是true
            guard shouldCreateTask() else { return }
            // 创建请求任务
            rootQueue.async { self.didCreateURLRequest(initialRequest, for: request) }
            return
        }
        // 由于没有设置拦截器,这块儿逻辑暂时不看
		...

    }

该方法中首先通过 convertible.asURLRequest()拿到URLRequest对象,并且判断reqeust是否有效。接下来进入到RequestConvertible的asURLRequest方法中,看看URLReques是如何初始化的。

func asURLRequest() throws -> URLRequest {
			// 创建URLRequest
            var request = try URLRequest(url: url, method: method, headers: headers)
            try requestModifier?(&request)
			// 对请求参数进行编码
            return try encoding.encode(request, with: parameters)
        }
extension URLRequest {
    public init(url: URLConvertible, method: HTTPMethod, headers: HTTPHeaders? = nil) throws {
        let url = try url.asURL()

        self.init(url: url)

        httpMethod = method.rawValue
        allHTTPHeaderFields = headers?.dictionary
    }
}
public func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest {
        var urlRequest = try urlRequest.asURLRequest()

        guard let parameters = parameters else { return urlRequest }

        do {
            let data = try JSONSerialization.data(withJSONObject: parameters, options: options)
			// 更新请求头中的Content-Type为application/json
            if urlRequest.headers["Content-Type"] == nil {
                urlRequest.headers.update(.contentType("application/json"))
            }
			// 设置httpBody
            urlRequest.httpBody = data
        } catch {
            throw AFError.parameterEncodingFailed(reason: .jsonEncodingFailed(error: error))
        }

        return urlRequest
    }

该方法做了两件事:

  • 初始化URLRequest,设置httpMethod,设置allHTTPHeaderFields
  • 调用JSONEncoding的encode方法,设置httpbody,还会更新请求头Content-Type为application/json,表示请求的数据为json数据

接着回到performSetupOperations(...)方法中,拿到URLRequest后,调用validate()方法判断请求是否有效,我们看一下这个方法:

public func validate() throws {
        if method == .get, let bodyData = httpBody {
            throw AFError.urlRequestValidationFailed(reason: .bodyDataInGETRequest(bodyData))
        }
    }

其实就是GET请求和设置httpbody不能同时存在,因为POST是将参数放在httpbody中(对应着JSONEncoding类),而GET请求会将参数拼接在URL后面(对应着URLEncoding类),不过URLEncoding类的encode实现并不只针对于GET方法,我们可以看下实现:

public func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest {
        var urlRequest = try urlRequest.asURLRequest()

        guard let parameters = parameters else { return urlRequest }

        if let method = urlRequest.method, destination.encodesParametersInURL(for: method) {
            guard let url = urlRequest.url else {
                throw AFError.parameterEncodingFailed(reason: .missingURL)
            }

            if var urlComponents = URLComponents(url: url, resolvingAgainstBaseURL: false), !parameters.isEmpty {
                let percentEncodedQuery = (urlComponents.percentEncodedQuery.map { $0 + "&" } ?? "") + query(parameters)
                urlComponents.percentEncodedQuery = percentEncodedQuery
                urlRequest.url = urlComponents.url
            }
        } else {
            if urlRequest.headers["Content-Type"] == nil {
                urlRequest.headers.update(.contentType("application/x-www-form-urlencoded; charset=utf-8"))
            }

            urlRequest.httpBody = Data(query(parameters).utf8)
        }

        return urlRequest
    }

可以看到,该方法会根据情况去判断选择拼接URL还是设置httpBody,我们点金destination.encodesParametersInURL(for: method)方法看看:

func encodesParametersInURL(for method: HTTPMethod) -> Bool {
            switch self {
            case .methodDependent: return [.get, .head, .delete].contains(method)
            case .queryString: return true
            case .httpBody: return false
            }
        }

当method为GET、HEAD、DELETE,或者URLEncoding的destination参数设置为queryString等情况时,会去拼接URL参数,否则就设置httpBody,但是跟JSONEncoding有一点不同,就是这里会设置请求头参数Content-Type默认为application/x-www-form-urlencoded; charset=utf-8****,这表示以表单的方式传输数据

接下来继续回到performSetupOperations(...)方法中,调用reqeust的didCreateInitialURLRequest()方法,看看该方法中做了什么事

func didCreateInitialURLRequest(_ request: URLRequest) {
        // 确保任务是在underlyingQueue中
        dispatchPrecondition(condition: .onQueue(underlyingQueue))
        // 将request添加到MutableState的requests数组中
        $mutableState.write { $0.requests.append(request) }
        // 由于没用到事件监听器,因此省略该代码
        ...
    }

上面方法其实主要就是将request请求添加到了mutableState的requests数组中,这里mutableState的作用是保证里面的所有属性都是安全的,可以看到mutableState属性前有个@Protected修饰,这是用到了swift属性包装器特性(可以参考这篇文章),可以点进Protected类看看具体核心实现

@propertyWrapper
final class Protected<T> {
    private let lock = UnfairLock()
    
    var wrappedValue: T {
        get { lock.around { value } }
        set { lock.around { value = newValue } }
    }
}

final class UnfairLock: Lock {
    private let unfairLock: os_unfair_lock_t

    init() {
        unfairLock = .allocate(capacity: 1)
        unfairLock.initialize(to: os_unfair_lock())
    }

    deinit {
        unfairLock.deinitialize(count: 1)
        unfairLock.deallocate()
    }

    fileprivate func lock() {
        os_unfair_lock_lock(unfairLock)
    }

    fileprivate func unlock() {
        os_unfair_lock_unlock(unfairLock)
    }
}

extension Lock {
    func around<T>(_ closure: () throws -> T) rethrows -> T {
        lock(); defer { unlock() }
        return try closure()
    }
}

该类的作用就是在读写属性的过程中通过加锁解锁,确保该过程是安全的。而Alamofire中采用的是互斥锁os_unfair_lock(可以参考这篇文章)来保证安全的。

那么还是回到performSetupOperations(...)方法中,接下来会判断request的state状态是否为isCancelled,这里其实状态是为resumed。因为在我们在最开始请求时,调用完AF.reqeust()后就立即调用了.response()方法,然后该方法又调用了appendResponseSerializer()方法

    func appendResponseSerializer(_ closure: @escaping () -> Void) {
        $mutableState.write { mutableState in
            mutableState.responseSerializers.append(closure)
            
			// 中间省略...
			
            if mutableState.state.canTransitionTo(.resumed) {
                underlyingQueue.async { if self.delegate?.startImmediately == true { self.resume() } }
            }
        }
    }

上面方法中,当startImmediately设置为true时,就会设置为resume状态。再接着往下走:

guard let adapter = adapter(for: request) else {
            // shouldCreateTask默认是true
            guard shouldCreateTask() else { return }
            // 创建请求任务
            rootQueue.async { self.didCreateURLRequest(initialRequest, for: request) }
            return
        }

就是根据传进去的request判断有没有设置请求拦截器,而默认是没有设置的,所以忽略。

创建请求Task,发送请求

接下来就调用self.didCreateURLRequest(initialRequest, for: request)方法去创建Task任务,具体看看该方法的实现:

func didCreateURLRequest(_ urlRequest: URLRequest, for request: Request) {
        dispatchPrecondition(condition: .onQueue(rootQueue))

		// 处理 创建urlRequest成功后的回调和cURL回调
        request.didCreateURLRequest(urlRequest)

        guard !request.isCancelled else { return }

        // 创建请求task, 并将reqeust和task一一对应
        let task = request.task(for: urlRequest, using: session)
        requestTaskMap[request] = task
        // 保存request,处理urlSessionTaskHandler回调
        request.didCreateTask(task)

        updateStatesForTask(task, request: request)
    }

该方法做了以下几件事

  • 首先request.didCreateURLRequest()方法主要就是处理urlRequestHandler和cURLHandler两个回调,一个是urlRequest创建完毕后的回调,一个是cURL的回调
  • 接着就是根据urlRequest生成Task,然后将request和task进行映射,保存在Session类的requestTaskMap属性中
  • request.didCreateURLRequest()方法则是保存request,然后处理urlSessionTaskHandler回调(创建Task成功后的回调)
  • 最后一步就是调用updateStatesForTask()方法,根据state的状态,做对应的操作,具体实现如下
func updateStatesForTask(_ task: URLSessionTask, request: Request) {
        dispatchPrecondition(condition: .onQueue(rootQueue))

        request.withState { state in
            switch state {
            case .initialized, .finished:
                break
            case .resumed:
                task.resume()
                rootQueue.async { request.didResumeTask(task) }
            case .suspended:
                task.suspend()
                rootQueue.async { request.didSuspendTask(task) }
            case .cancelled:
                task.resume()
                task.cancel()
                rootQueue.async { request.didCancelTask(task) }
            }
        }
    }

到此,整个请求的创建、请求任务的开启就完成了

请求回调

接下来就是处理请求过程中的回调,在最开始初始化Session时,就设置URLSession的delegate默认为SessionDelegate类,因此请求的回调处理到在SessionDelegate类中

首先是调用URLSessionDataDelegate的didReceive代理方法,处理接收到的数据:

open func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
        eventMonitor?.urlSession(session, dataTask: dataTask, didReceive: data)

        if let request = request(for: dataTask, as: DataRequest.self) {
            request.didReceive(data: data)
        } else if let request = request(for: dataTask, as: DataStreamRequest.self) {
            request.didReceive(data: data)
        } else {
            assertionFailure("dataTask did not find DataRequest or DataStreamRequest in didReceive")
            return
        }
    }

该代理方法内部其实主要就是调用request.didReceive(data: data) ,进去看看实现:

    func didReceive(data: Data) {
    	// 拼接数据
        if self.data == nil {
            mutableData = data
        } else {
            $mutableData.write { $0?.append(data) }
        }

		// 更新请求数据的进度
        updateDownloadProgress()
    }
    
    func updateDownloadProgress() {
    	// 请求接收到的值
        let totalBytesReceived = Int64(data?.count ?? 0)
        // 期望数据值
        let totalBytesExpected = task?.response?.expectedContentLength ?? NSURLSessionTransferSizeUnknown

        downloadProgress.totalUnitCount = totalBytesExpected
        downloadProgress.completedUnitCount = totalBytesReceived
		// 处理请求进度的回调
        downloadProgressHandler?.queue.async { self.downloadProgressHandler?.handler(self.downloadProgress) }
    }

该方法主要做了两件事:

  • 保存接收到的数据
  • 根据接受的数据值和期望值计算出进度,然后处理请求进度的回调

当响应完了之后,就会调用URLSessionTaskDelegate的didCompleteWithError代理方法:

open func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
    eventMonitor?.urlSession(session, task: task, didCompleteWithError: error)

	// 从requestTaskMap中,根据task取出reqeust
    let request = stateProvider?.request(for: task)

	// 调用完成请求任务
    stateProvider?.didCompleteTask(task) {
        request?.didCompleteTask(task, with: error.map { $0.asAFError(or: .sessionTaskFailed(error: $0)) })
    }
}

该方法首先调用stateProvider(也就是Session类,最开始初始化时,是将SessionDelegate的delegate设置为了自己)的request(for: task)代理方法,从requestTaskMap中根据task取出reqeust。紧接着就是调用代理方法didCompleteTask(),可以点进去看看:

    func didCompleteTask(_ task: URLSessionTask, completion: @escaping () -> Void) {
        dispatchPrecondition(condition: .onQueue(rootQueue))
		// 是否需要在完成任务后解除关联reqeust和task的关联
        let didDisassociate = requestTaskMap.disassociateIfNecessaryAfterCompletingTask(task)

        if didDisassociate {
            completion()
        } else {
            waitingCompletions[task] = completion
        }
    }

首先通过disassociateIfNecessaryAfterCompletingTask()方法判断是否要解除reqeust和task的关联,该方法的内部其实主要就是根据taskEvents参数内的.completed.metricsGathered去进行判断。其实在之前创建完urlRequest后,将dataReqeust和task通过字典requestTaskMap映射时,其初始化就将.completed.metricsGathered全部设置成false,参考如下代码:

	// Session
    func didCreateURLRequest(_ urlRequest: URLRequest, for request: Request) {
        此处省略一段代码...
        
        let task = request.task(for: urlRequest, using: session)
        requestTaskMap[request] = task	
        
        此处省略一段代码...
    }


	// RequestTaskMap
	subscript(_ request: Request) -> URLSessionTask? {
        get { requestsToTasks[request] }
        set {
        	此处省略一段代码...
            taskEvents[newValue] = (completed: false, metricsGathered: false)
        }
    }

继续回到Session的didCompleteTask()代理方法中,如果解除request和task关系,则直接调用completion回调,反之会将completion回调放进waitingCompletions中,将task和completion进行映射,稍后再取出执行。而completion回调(也就是dataReqeust的didCompleteTask()方法),主要就是调用retryOrFinish(error: self.error)方法,该方法会根据错误和代理方法来决定本次请求是需要重试还是结束

    func retryOrFinish(error: AFError?) {
        dispatchPrecondition(condition: .onQueue(underlyingQueue))
		// 无错误,直接结束
        guard let error = error, let delegate = delegate else { finish(); return }
		// 有错误,根据retryResult代理方法去判断如何重试
        delegate.retryResult(for: self, dueTo: error) { retryResult in
            switch retryResult {
            case .doNotRetry:
                self.finish()
            case let .doNotRetryWithError(retryError):
                self.finish(error: retryError.asAFError(orFailWith: "Received retryError was not already AFError"))
            case .retry, .retryWithDelay:
                delegate.retryRequest(self, withDelay: retryResult.delay)
            }
        }
    }

接着进入到finish()方法,该方法中核心就是调用processNextResponseSerializer()方法处理响应序列回调,点进去看看

    func processNextResponseSerializer() {
    	// 有响应序列回调,就处理;没有就表示请求完成,调用响应序列完成回调
        guard let responseSerializer = nextResponseSerializer() else {
			// 此处先省略逻辑,后面再看
            return
        }
        serializationQueue.async { responseSerializer() }
    }

该方法要分成两种情况,主要是看nextResponseSerializer()中的响应序列回调是否处理完毕。首先先回调最开始的请求代码中,看下response的回调干了什么事

// 最开始的请求代码
AF.request(url, method: .post, parameters: parameters, encoding: JSONEncoding.default, headers: httpHeaders).response { response in
 	...
}

// DataRequest的响应代码
public func response(queue: DispatchQueue = .main, completionHandler: @escaping (AFDataResponse<Data?>) -> Void) -> Self {
	// 添加响应序列回调
    appendResponseSerializer {
        // 响应序列回调...
    }

    return self
}

response方法其实就是添加响应序列回调,至于回调中干了什么事,下面再说

注意,这里需要分清楚响应序列回调响应序列完成回调,先直接说明两者的区别,后面再从代码中看
1、响应序列回调是存储在responseSerializers属性中,也就是上面方法中的回调(拿到response,调用responseSerializerDidComplete)
2、响应序列完成回调则是存储在responseSerializerCompletions中,该回调就是我们在最外层response的回调中写的代码(例如拿到data,解析成json,然后json转成dictionary,)

然后进入appendResponseSerializer()方法,该方法主要就是将响应序列回调添加到responseSerializers

func appendResponseSerializer(_ closure: @escaping () -> Void) {
    $mutableState.write { mutableState in
   		// 添加响应序列回调
        mutableState.responseSerializers.append(closure)

        if mutableState.state == .finished {
            mutableState.state = .resumed
        }

        if mutableState.responseSerializerProcessingFinished {
            underlyingQueue.async { self.processNextResponseSerializer() }
        }

        if mutableState.state.canTransitionTo(.resumed) {
            underlyingQueue.async { if self.delegate?.startImmediately == true { self.resume() } }
        }
    }
}

接着还是回到processNextResponseSerializer()方法中,通过nextResponseSerializer()依次取出responseSerializers中的响应序列回调,然后执行该回调。该回调实现如下:

{
            let result = AFResult<Data?>(value: self.data, error: self.error)

            self.underlyingQueue.async {
            // 获取DataResponse实例
                let response = DataResponse(request: self.request,
                                            response: self.response,
                                            data: self.data,
                                            metrics: self.metrics,
                                            serializationDuration: 0,
                                            result: result)

                self.eventMonitor?.request(self, didParseResponse: response)
			// 执行响应序列完成回调
                self.responseSerializerDidComplete { queue.async { completionHandler(response) } }
            }
        }

该回调首先根据请求完成拿到的data以及其他参数生成DataResponse实例,然后调用responseSerializerDidComplete()方法,该方法的回调就是执行响应序列完成回调,点进方法看看

func responseSerializerDidComplete(completion: @escaping () -> Void) {
    $mutableState.write { $0.responseSerializerCompletions.append(completion) }
    processNextResponseSerializer()
}

该方法内部就是将响应序列完成回调添加到responseSerializerCompletions属性中,然后又回到processNextResponseSerializer()中,如此反复,直到nextResponseSerializer()中的响应序列回调都取出来了,就开始走响应序列回调都处理完毕的逻辑,也就是之间看的这段代码中else的逻辑

func processNextResponseSerializer() {
    	// 有响应序列回调,就处理;没有就表示请求完成,调用响应序列完成回调
        guard let responseSerializer = nextResponseSerializer() else {
            var completions: [() -> Void] = []

            $mutableState.write { mutableState in
            	// 取出响应序列完成回调,赋值
                completions = mutableState.responseSerializerCompletions

                // 清除响应序列回调和响应序列完成回调
                mutableState.responseSerializers.removeAll()
                mutableState.responseSerializerCompletions.removeAll()
				
				// 状态设置为finished
                if mutableState.state.canTransitionTo(.finished) {
                    mutableState.state = .finished
                }
				// 标记响应序列回调处理完毕
                mutableState.responseSerializerProcessingFinished = true
                mutableState.isFinishing = false
            }

			// 调用响应序列完成的回调(也就是response方法的回调)
            completions.forEach { $0() }

            // 清除activeRequests中该次请求,并调用finishHandlers请求结束回调(该回调需自行添加)
            cleanup()

            return
        }

        serializationQueue.async { responseSerializer() }
    }

根据注释可以看到,主要是将响应序列完成回调都取出来,然后清除保存的这些回调以及请求,并且将状态设置为响应处理完毕,最后调用响应序列完成回调,做列如JSON序列化,转Dictionary,转Model等一些操作

那么到此,整个请求流程逻辑就走完了。但是还是有些地方没有讲解清楚的,例如下载、上传等请求方式、监听器、拦截器、请求验证、错误处理、重定向等等细节方面,后面会单独再开说一下

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值