Alamofire的异步链式调用

Alamofire是大名鼎鼎的swift网络框架。 对Alamofire不是很熟悉的朋友,可以先看这篇文章

链式调用例子

extension Int {
    func add(_ num: Int) -> Int {
        return self + num
    }

    func minus(_ num: Int) -> Int {
        return self - num
    }
}

print(1.add(2).minus(3))  // 输出毫无疑问是0
复制代码

Alamofire例子

一个简单的用Alamofire发起的请求,请求结果回调后将解析数据

Alamofire.request(url).responseJSON { (json) in
            // do something
        }
复制代码

可以看到下面两个方法都返回DataRequest,这是链式调用的前提。 @discardableResult的作用是取消没有使用返回值 编译器给出的警告。

@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
    )
}
复制代码
// extension DataRequest
    @discardableResult
    public func responseJSON(
        queue: DispatchQueue? = nil,
        options: JSONSerialization.ReadingOptions = .allowFragments,
        completionHandler: @escaping (DataResponse<Any>) -> Void)
        -> Self  // 这里的Self 就是 DataRequest
    {
        return response(
            queue: queue,
            responseSerializer: DataRequest.jsonResponseSerializer(options: options),
            completionHandler: completionHandler
        )
    }

复制代码

都知道网络请求是一个异步的过程。 请各位思考一个问题,在链式调用中如何等待第一个方法回调结束后再执行第二个方法的操作? 也就是如何等待request()方法回调后再去执行responsJSON()方法里的操作?

Alamofire是使用NSOperationQueue来实现

  • 首先在处理request回调的delegate定义了一个队列。
  • 这个队列在创建的时候是挂起的,然后不断的往里塞任务:比如responseJSON等。然后等回调完成的时候,再唤醒这个队列,按顺序的执行这些任务。
open let queue: OperationQueue

init(task: URLSessionTask?) {
        _task = task

        self.queue = {
            let operationQueue = OperationQueue()
            // 串行队列 
            operationQueue.maxConcurrentOperationCount = 1
            // 将队列挂起
            operationQueue.isSuspended = true
            operationQueue.qualityOfService = .utility
            return operationQueue
        }()
    }
复制代码

实践

做一个小demo

NetworkTask().request().responseJSON { (data) in
    print("data - \(data)")
}
复制代码
class NetworkTask {
    // 专门处理 请求完成后的回调
    private let delegate = NetworkDelegate()
    
    @discardableResult
    public func request() -> Self {
        print("开始网络请求")
        // 模拟网络请求过程 3s
        DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 3) {
            print("请求成功")
            self.delegate.handleRequest()
        }
        return self
    }
    
    @discardableResult
    public func responseJSON(compeletionHandler: @escaping (_ data: String) -> ()) -> Self {
        print("response任务加入队列")
        delegate.queue.addOperation {
            print("response任务开始执行 - 当前线程:\(Thread.current)")
            DispatchQueue.main.async {
                print("开始执行response任务回调 - 当前线程:\(Thread.current)")
                compeletionHandler(self.delegate.data)
            }
        }
        return self
    }
}

class NetworkDelegate {
    
    let queue: OperationQueue = {
        let queue = OperationQueue()
        queue.maxConcurrentOperationCount = 1
        queue.isSuspended = true
        return queue
    }()
    
    var data = ""
    
    func handleRequest() {
        // do something...
        data = "数据"
        print("处理数据")
        // 唤醒队列
        queue.isSuspended = false
    }
}
复制代码

这个queue也可以用GCD实现

let queue: DispatchQueue = {
       let queue = DispatchQueue(label: "network.task")
        queue.suspend()
        return queue
    }()
复制代码
func handleRequest() {
        // do something...
        data = "数据"
        print("处理数据")
        // 唤醒队列
        queue.resume()
    }
复制代码
@discardableResult
    public func responseJSON(compeletionHandler: @escaping (_ data: String) -> ()) -> Self {
        print("response任务加入队列")
        delegate.queue.async {
            print("response任务开始执行 - 当前线程:\(Thread.current)")
            DispatchQueue.main.async {
                print("开始执行response任务回调 - 当前线程:\(Thread.current)")
                compeletionHandler(self.delegate.data)
            }
        }
        return self
    }
复制代码

转载于:https://juejin.im/post/5d0df1fe5188253272474837

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值