Alamofire中如何响应请求的:
Alamofire
.request("https://ip.cn")
.responseData { respons in //响应请求
print(String(bytes: respons.data!, encoding: .utf8)!)
}
1 看看源码
先去DataRequest的responseData()方法内部看看源码:
@discardableResult
public func responseData(
queue: DispatchQueue? = nil, //执行响应闭包的队列,默认为空
//解析完成后执行的闭包
completionHandler: @escaping (DataResponse<Data>) -> Void)
-> Self
{
return response(
queue: queue,
responseSerializer: DataRequest.dataResponseSerializer(),
completionHandler: completionHandler
)
}
- queue参数:
解析完毕后的闭包在哪个队列执行 - completionHandler参数:
解析完毕后,调用的闭包,请求结果会以Data的形式返回。 - 方法内部:
在方法内部,调用了自身的response()方法。
接下来,看看response()方法的源码:
@discardableResult
public func response<T: DataResponseSerializerProtocol>(
queue: DispatchQueue? = nil,
responseSerializer: T,
completionHandler: @escaping (DataResponse<T.SerializedObject>) -> Void)
-> Self
{
delegate.queue.addOperation {//在请求队列中增加操作
//调用传入的解析器解析请求到的数据
let result = responseSerializer.serializeResponse(
self.request,
self.response,
self.delegate.data,
self.delegate.error
)
//生成闭包中的DataResponse
var dataResponse = DataResponse<T.SerializedObject>(
request: self.request,
response: self.response,
data: self.delegate.data,
result: result,
timeline: self.timeline
)
//增加请求时的信息,比如请求了几次,一共耗时等信息
dataResponse.add(self.delegate.metrics)
//调用传入的闭包
(queue ?? DispatchQueue.main).async { completionHandler(dataResponse) }
}
return self
}
- responseSerializer参数:
响应是如何解析的,使用的是DataRequest.dataResponseSerializer() - 方法内部:
具体操作看注释,方法内部主要作用是:给请求队列添加解析的操作,操作完毕后在给定的队列中调用传入的闭包。 - 通过源码可以看出,闭包中DataResponse参数中,request、response、data、result、timeline这几个属性,是通过请求的返回生成的,大多数我们也只是需要data属性。
- 我们还可以知道,执行闭包的队列我们是可以自己指定的,比如需要闭包在指定的子线程执行,传入子线程即可。否则默认是在主线程执行闭包。
2 看看默认的解析器内部都干了什么
public static func dataResponseSerializer() -> DataResponseSerializer<Data> {
return DataResponseSerializer { _, response, data, error in
return Request.serializeResponseData(response: response, data: data, error: error)
}
}
这个方法是DataRequest扩展的一个方法,方法内部初始化了一个DataResponseSerializer的实例,传入了一个闭包,闭包中调用了Request的类方法serializeResponseData()。
看起来很绕,我们一步一步来看,先看看闭包中调用的Request的类方法serializeResponseData()。
public static func serializeResponseData(response: HTTPURLResponse?, data: Data?, error: Error?) -> Result<Data> {
//判断请求是否发生了错误
guard error == nil else { return .failure(error!) }
//取出response,如果是204、205状态码,直接返回空数据
if let response = response, emptyDataStatusCodes.contains(response.statusCode) { return .success(Data()) }
//取出data
guard let validData = data else {
return .failure(AFError.responseSerializationFailed(reason: .inputDataNil))
}
//执行成功的闭包
return .success(validData)
}
做了哪些操作看注释。总结一下,本方法作用就是对原生的请求response进行响应的处理。
接下来看看DataResponseSerializer这个结构体。
public struct DataResponseSerializer<Value>: DataResponseSerializerProtocol {
public typealias SerializedObject = Value
public var serializeResponse: (URLRequest?, HTTPURLResponse?, Data?, Error?) -> Result<Value>
public init(serializeResponse: @escaping (URLRequest?, HTTPURLResponse?, Data?, Error?) -> Result<Value>) {
self.serializeResponse = serializeResponse
}
}
可以看到,该方法内部使用了一个属性保存传入的解析方法,在后续需要解析时直接调用属性进行解析。
3 总结
通过源码,我们可以知道如下几件事:
1.调用responseData()方法时,我们可以指定闭包和闭包执行的线程。
2.responseData()方法内部是调用自身的response()方法,也就是说,response()这个方法我们可以自己调用,传入自己需要的response解析器满足自定义需求。
3.可以通过respons.metrics属性获得请求过程中详细的信息。
4.依次类推,responseJSON、responseString等方法,也是这样。










网友评论