Alamofire 源码解析

Alamofire 浅析 <三>SessionMan

2018-08-31  本文已影响33人  狼性刀锋

request core code

  // generate DataRequest
  // @discardableResult 注解可以避免: request(urlRequest) 时,引起编译器警告, 通常需要这么写 _ = request(urlRequest)  才能避免警告
    @discardableResult
    open func request(_ urlRequest: URLRequestConvertible) -> DataRequest {
        var originalRequest: URLRequest?

        do {
            // 转成 URLRequest
            originalRequest = try urlRequest.asURLRequest()
            
            // generate TaskConvertible
            let originalTask = DataRequest.Requestable(urlRequest: originalRequest!)
            
            // generate URLSessionTask
            let task = try originalTask.task(session: session, adapter: adapter, queue: queue)

            // generate DataRequest
            let request = DataRequest(session: session, requestTask: .data(originalTask, task))
            
          // 这里使用了下标访问成员属性,具体后面详细说明
          // delegate 为SessionDelegate 类型
          // 将 task 存入 SessionDelegate 的 requests容器中
          //  requests 原型 var requests: [Int: Request] = [:] , key = task.id
            delegate[task] = request
 
          // URLSessionTask  resume
            if startRequestsImmediately { request.resume() }

            return request
        } catch {
            return request(originalRequest, failedWith: error)
        }
    }


// 异常处理
    // MARK: Private - Request Implementation

    private func request(_ urlRequest: URLRequest?, failedWith error: Error) -> DataRequest {
        var requestTask: Request.RequestTask = .data(nil, nil)


        if let urlRequest = urlRequest {  // 说明生成urlRequest 成功
        
            // 重新生成 TaskConvertible
            let originalTask = DataRequest.Requestable(urlRequest: urlRequest)
            requestTask = .data(originalTask, nil)
        }

        let underlyingError = error.underlyingAdaptError ?? error

        // 重新生成  DataRequest
       // 和之前的区别在于error 不为空, requestTask 的session task 为空
        let request = DataRequest(session: session, requestTask: requestTask, error: underlyingError)

        // 如果 retrier 不为空,且当前error为AdaptError,则执行retry
        if let retrier = retrier, error is AdaptError {
            allowRetrier(retrier, toRetry: request, with: underlyingError)
        } else {
            // 由于URLSessionTask 为空, 事实上该操作不会触发网络请求
            if startRequestsImmediately { request.resume() }
        }

        return request
    }


    enum RequestTask {
        case data(TaskConvertible?, URLSessionTask?)
        case download(TaskConvertible?, URLSessionTask?)
        case upload(TaskConvertible?, URLSessionTask?)
        case stream(TaskConvertible?, URLSessionTask?)
    }

分析

和之前描述一致:
URLRequestConvertible -> URLRequest
TaskConvertible -> URLSessionTask
initRequestWithURLSessionTask:TaskConvertible -> Request
sessionDelegate catch URLSessionTask (注: 这一步是为了当触发SessionDelegate的时候,将消息转发给TaskDelegate)
Request resume
return Request

这里有意思的地方在于它出错的情况下是怎么处理的,这里在URLRequest或者URLSessionTask都为空的情况下,仍然返回DataRequest, 这样便于统一做错误处理,通常多数人会选择throw, 那么就需要检测异常,like this

do {
    let request = try SessionManager.request 
    request.response { result in
        //  if error do errorHandle
       }
} catch {
    ...
    errorHandle
}


而统一返回DataRequest ,我们就可以在最后面做处理


let request = SessionManager.request 
    request.response { result in
   
        //  if error do errorHandle

     }

显然后者会让我们的代码变得更加简洁。

上一篇 下一篇

猜你喜欢

热点阅读