程序员

Swift:Alamofire的异步链式调用

2018-04-06  本文已影响424人  SoolyChristina

Alamofire是很常用的swift网络库,本文将分析Alamofire的链式调用。
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来实现

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
    }
上一篇 下一篇

猜你喜欢

热点阅读