Alamofire 执行同步请求
更新于:2022-02-21 标签:AlamofireSwift
网络编程时,当业务逻辑变得复杂,难免会遇到回调嵌套。Javascript
的async/await
异步处理方案让我们不再受callback
回调噩梦的困扰。
本文介绍一种让Alamofire
实现类似于async/await
的同步请求方案,优雅摆脱回调地狱。演示如下,基于 Alamofire 5.0+。
// 异步请求
AF.request(LOGIN_URL, method: .post, parameters: params).responseDecodable(of: MyNetWorkModel.self) { (response) in
if response.result == .success { ... }
}
// 同步请求
let response = AF.request(LOGIN_URL, method: .post, parameters: params).responseDecodable(of: MyNetWorkModel.self)
if response.result == .success { ... }
实现
信号量实现等待
简单复习一下信号量,DispatchSemaphore 声明时规定信号量计数的初始值,wait()
方法会让信号量值减一,signal()
会让信号量值加一。当信号量值为 0 时等待(直到 timeout),否则正常执行。
给Alamofire
的DataRequest
类添加extension
,用信号量实现完成前等待。
import Alamofire
extension DataRequest {
public func responseSync<T: DataResponseSerializerProtocol>(responseSerializer: T) -> AFDataResponse<T.SerializedObject> {
let semaphore = DispatchSemaphore(value: 0)
var result: AFDataResponse<T.SerializedObject>!
self.response(queue: DispatchQueue.global(qos: .default), responseSerializer: responseSerializer) { response in
result = response
semaphore.signal()
}
_ = semaphore.wait(timeout: DispatchTime.distantFuture)
return result
}
}
定义同名方法
再根据业务需求定义实现同步的同名方法,调用定义的 responseSync 方法即可,这里以 responseDecodable 方法举例。
public func responseDecodable<T: Decodable>(of type: T.Type = T.self) -> AFDataResponse<T> {
return self.responseSync(responseSerializer: DecodableResponseSerializer(
dataPreprocessor: DecodableResponseSerializer<T>.defaultDataPreprocessor,
decoder: JSONDecoder(),
emptyResponseCodes: DecodableResponseSerializer<T>.defaultEmptyResponseCodes,
emptyRequestMethods: DecodableResponseSerializer<T>.defaultEmptyRequestMethods)
)
}
注意
不能放在主线程中使用。刷新主线程数据时记得加上:
DispatchQueue.main.async { ... }