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
}
显然后者会让我们的代码变得更加简洁。
网友评论