Alamofire的流程(一)
2018-08-08 本文已影响16人
嘻嘻zhy
普通请求
在官方demo中,alamofire给出了示例代码。
Alamofire.request("https://httpbin.org/get").responseJSON { response in
print("Request: \(String(describing: response.request))") // original url request
print("Response: \(String(describing: response.response))") // http url response
print("Result: \(response.result)") // response serialization result
if let json = response.result.value {
print("JSON: \(json)") // serialized json response
}
if let data = response.data, let utf8Text = String(data: data, encoding: .utf8) {
print("Data: \(utf8Text)") // original server data as UTF8 string
}
}
在实际源码中,到底是怎么工作的呢?
request函数
/// Creates a `DataRequest` using the default `SessionManager` to retrieve the contents of the specified `url`,
/// `method`, `parameters`, `encoding` and `headers`.
@discardableResult
public func request(
_ url: URLConvertible,
method: HTTPMethod = .get,
parameters: Parameters? = nil,
encoding: ParameterEncoding = URLEncoding.default,
headers: HTTPHeaders? = nil)
-> DataRequest
{
return SessionManager.default.request(
url,
method: method,
parameters: parameters,
encoding: encoding,
headers: headers
)
}
URLConvertible
/// Types adopting the `URLConvertible` protocol can be used to construct URLs, which are then used to construct
/// URL requests.
public protocol URLConvertible {
/// Returns a URL that conforms to RFC 2396 or throws an `Error`.
///
/// - throws: An `Error` if the type cannot be converted to a `URL`.
///
/// - returns: A URL or throws an `Error`.
func asURL() throws -> URL
}
extension String: URLConvertible {
/// Returns a URL if `self` represents a valid URL string that conforms to RFC 2396 or throws an `AFError`.
///
/// - 如果`self`不是一个有效的URL字符串, 就会抛出`AFError.invalidURL` 异常。
/// - returns: A URL or throws an `AFError`.
public func asURL() throws -> URL {
guard let url = URL(string: self) else { throw AFError.invalidURL(url: self) }
return url
}
}
URLConvertible
协议是为了将String类型的字符串快速转化为URL类型。
SessionManager
SessionManager
是用来负责创建和管理请求的对象,就如同底层的NSURLSession
。
default
/// 默认的`SessionManager`实例, 由Alamofire顶层的请求方法使用,直接适用于任何特定请求.
public static let `default`: SessionManager = {
let configuration = URLSessionConfiguration.default
configuration.httpAdditionalHeaders = SessionManager.defaultHTTPHeaders
return SessionManager(configuration: configuration)
}()
request(1)
@discardableResult
open func request(
_ url: URLConvertible,
method: HTTPMethod = .get,
parameters: Parameters? = nil,
encoding: ParameterEncoding = URLEncoding.default,
headers: HTTPHeaders? = nil)
-> DataRequest
{
var originalRequest: URLRequest?
do {
originalRequest = try URLRequest(url: url, method: method, headers: headers)
let encodedURLRequest = try encoding.encode(originalRequest!, with: parameters)
return request(encodedURLRequest)
} catch {
return request(originalRequest, failedWith: error)
}
}
通过URL Method Header生成一个URLRequest, 并通过制定的ParameterEncoding方法,将参数合并到URLRequest中,根据是否成功,执行下一个request方法。
request(2)
/// Creates a `DataRequest` to retrieve the contents of a URL based on the specified `urlRequest`.
///
/// If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned.
///
/// - parameter urlRequest: The URL request.
///
/// - returns: The created `DataRequest`.
@discardableResult
open func request(_ urlRequest: URLRequestConvertible) -> DataRequest {
var originalRequest: URLRequest?
do {
originalRequest = try urlRequest.asURLRequest()
let originalTask = DataRequest.Requestable(urlRequest: originalRequest!)
let task = try originalTask.task(session: session, adapter: adapter, queue: queue)
let request = DataRequest(session: session, requestTask: .data(originalTask, task))
delegate[task] = request
if startRequestsImmediately { request.resume() }
return request
} catch {
return request(originalRequest, failedWith: error)
}
}
request(3)
// MARK: Private - Request Implementation
private func request(_ urlRequest: URLRequest?, failedWith error: Error) -> DataRequest {
var requestTask: Request.RequestTask = .data(nil, nil)
if let urlRequest = urlRequest {
let originalTask = DataRequest.Requestable(urlRequest: urlRequest)
requestTask = .data(originalTask, nil)
}
let underlyingError = error.underlyingAdaptError ?? error
let request = DataRequest(session: session, requestTask: requestTask, error: underlyingError)
if let retrier = retrier, error is AdaptError {
allowRetrier(retrier, toRetry: request, with: underlyingError)
} else {
if startRequestsImmediately { request.resume() }
}
return request
}