Alamofire的異步鏈式調用

Alamofire是大名鼎鼎的swift網絡框架。 對Alamofire不是很熟悉的朋友,能夠先看這篇文章git

鏈式調用例子

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發起的請求,請求結果回調後將解析數據github

Alamofire.request(url).responseJSON { (json) in
            // do something
        }
複製代碼

能夠看到下面兩個方法都返回DataRequest,這是鏈式調用的前提。 @discardableResult的做用是取消沒有使用返回值 編譯器給出的警告。json

@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()方法裏的操做?swift

Alamofire是使用NSOperationQueue來實現api

  • 首先在處理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
        }()
    }
複製代碼

實踐

作一個小demobash

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
    }
複製代碼
相關文章
相關標籤/搜索