翻遍百度没事找到合适的参考文章,最终找到了这篇以图片加载讲解队列的文章https://juejin.im/post/5b6047dae51d4517580e1627
问题:项目进入首页需要进行多个多次的网络请求,如果有一个请求失败或者网络问题仍然会请求其他接口。(非AFN,原生网络请求方式)
思路:让网络请求以队列的方式进行,先进先出,一个失败取消剩余请求。
实现:
1、保存请求的类
//请求状态枚举
enum RequestState {
case new,start,failed,success
}
//请求记录
class LZUrlRecord {
let name: String
let url:String
var state = RequestState.new
var dicParamter:Dictionary<String,Any>?
var strParamter:String?
var completion:((RequestState,Dictionary<String,Any>)->())?
init(name:String,url:String){
self.name = name
self.url = url
}
}
2、队列,及队列中Operation实现
//保存队列操作的单例
let sharePendingOperations = PendingOperations()
class PendingOperations{
//请求队列
lazy var requestQueue:OperationQueue = {
var queue = OperationQueue()
queue.name = "Request queue"
queue.maxConcurrentOperationCount = 1
return queue
}()
//队列挂起
func suspendAllOperations() {
self.requestQueue.isSuspended = true
}
// 队列重启
func resumeAllOperations() {
self.requestQueue.isSuspended = false
}
// 重置队列
func resetAllOperations() {
self.requestQueue.cancelAllOperations()
self.resumeAllOperations()
}
}
//Operation是一个抽象类,专为子类化而设计。每个子类代表一个特定的任务,如前面的图所示。
//自定义请求任务
class LZRequestTask: Operation {
let urlRecord:LZUrlRecord
init(_ urlRecord:LZUrlRecord){
self.urlRecord = urlRecord
}
override func main() {
//每次启动一个operation时将整个队列挂起,暂停所有operations
sharePendingOperations.suspendAllOperations()
//发起网络请求
RNetUtil.shareManager.requestTPOST(url: urlRecord.url, paramter: urlRecord.strParamter!) { (state, data) in
//有回调将网络状态及请求结果返回
if let handler = self.urlRecord.completion{
self.urlRecord.state = state
handler(state, data)
}
}
}
}
3、网络请求
//网络请求
func requestPOSTWithQueue(url:String,
paramter:String,
completion:@escaping ((RequestState,Dictionary<String,Any>)->Void)) {
//定义请求记录实例
let urlRecord = LZUrlRecord.init(name: url, url: url)
urlRecord.strParamter = paramter
// 实现回调
urlRecord.completion = {
(state,data) in
if state == .success{
// 成功时重新启动操作队列
sharePendingOperations.resumeAllOperations()
}else{
// 失败时重置操作队列
sharePendingOperations.resetAllOperations()
}
//将网络状态和返回值传回主线程刷新ui
completion(state,data)
}
// 网络请求任务实例
let requestTask = LZRequestTask.init(urlRecord)
//将网络请求任务加入操作队列
sharePendingOperations.requestQueue.addOperation(requestTask)
}
4、viewController里发起网络请求
//同时发起多个网络请求
func testRequestTasks() {
RNetUtil.shareManager.requestPOSTWithQueue(url: url, paramter: "0") { (state, data) in
print(state,data)
}
RNetUtil.shareManager.requestPOSTWithQueue(url: url, paramter: "0") { (state, data) in
print(state,data)
}
RNetUtil.shareManager.requestPOSTWithQueue(url: url, paramter: "0") { (state, data) in
print(state,data)
}
}
5、请求结果
失败时
成功时
基本解决了文章开头提出的问题。
有什么改进意见或者好的想法,欢迎大家提出。