美文网首页
Alamofire-Response

Alamofire-Response

作者: yahibo | 来源:发表于2019-08-25 14:13 被阅读0次
    response.png

    response为数据请求响应结果,封装了URLRequest、时间轴、请求错误信息,请求成功的数据等信息,方便开发人员取用。

    一、业务层获取响应数据

    Alamofire.request(url,method: .post,parameters: nil)
        .response{ response in
        print("response:\(response)")
    }
    
    • response方法通过闭包向外传递响应数据

    1、response-方法

    方法实现在ResponseSerialization.swift文件中,是对响应结果的封装,提供序列化和不序列化请求结果的方法,其实都是对结果的一个处理封装,因此都放在该文件是合理的。下面看一下默认响应处理:

    public func response(queue: DispatchQueue? = nil, completionHandler: @escaping (DefaultDataResponse) -> Void) -> Self {
        delegate.queue.addOperation {
            (queue ?? DispatchQueue.main).async {
                var dataResponse = DefaultDataResponse(
                    request: self.request,
                    response: self.response,
                    data: self.delegate.data,
                    error: self.delegate.error,
                    timeline: self.timeline
                )
                dataResponse.add(self.delegate.metrics)
                completionHandler(dataResponse)
            }
        }
        return self
    }
    
    • 该方法为DataRequest的扩展方法,返回self,可以继续链式调用,为方便调用,在Request类中这种写法比较常见
    • 创建了DefaultDataResponse对象,并初始化,将请求过程中所有参数整合

    该方法在序列化文件中,都是对Request相关子类的扩展,以便于业务层调用。前面有讲到过,Request是面向业务层的,提供responseJSON、downloadProgress、response等方法。

    DefaultDataResponse为一个结构体,在Response.swift文件中,是默认的存储结构。

    2、Response-结构体

    Response.swift中声明了多个结构体,应对不同的使用场景。分类如下:

    DefaultDataResponse
    DataResponse
    DefaultDownloadResponse
    DownloadResponse
    

    在业务层调用的response中对应的为DefaultDataResponse结构体,此处没有做序列化处理,只是对数据进行整合。业务层的方法调用和内部结构体的联系如下:

    1、response{ response in } -> DefaultDataResponse 只做数据整合
    2、responseJSON{ response in } -> DataResponse 对请求数据做序列化处理再整合
    3、downloadProgress.response -> DefaultDownloadResponse 整合存储下载相关信息
    4、downloadProgress.response(responseSerializer) -> DownloadResponse 整合存储下载相关信息

    为什么没有upload对应的结构体呢,因为upload返回结果就是普通的数据返回,以上提供的方法便可公用。

    通过Request对象的一步步调用,最终数据会处理未Response的形式,通过闭包调用向业务层发送response类型消息。

    二、DataResponseSerializer-序列化器

    Request类中提供了序列化处理和非序列化处理,可以根据需要来调用。下面看一下,序列化器是如何序列化的。方法入口如下:

    Alamofire.request(url,method: .post,parameters: nil).responseJSON {
        (response) in
        switch response.result{
        case .success(let json):
            print("json:\(json)")
            break
        case .failure(let error):
            print("error:\(error)")
            break
        }
    }
    
    • responseJSON就是获取一个json类型的数据,原始数据在方法内部被序列化过
    public func responseJSON(
        queue: DispatchQueue? = nil,
        options: JSONSerialization.ReadingOptions = .allowFragments,
        completionHandler: @escaping (DataResponse<Any>) -> Void)
        -> Self
    {
        return response(
            queue: queue,
            responseSerializer: DataRequest.jsonResponseSerializer(options: options),
            completionHandler: completionHandler
        )
    }
    
    • jsonResponseSerializer实际上是一个函数指针,供response内部调用,通过该函数来处理数据

    jsonResponseSerializer实现:

    public static func jsonResponseSerializer(
        options: JSONSerialization.ReadingOptions = .allowFragments)
        -> DataResponseSerializer<Any>
    {
        return DataResponseSerializer { _, response, data, error in
            return Request.serializeResponseJSON(options: options, response: response, data: data, error: error)
        }
    }
    
    • 实现闭包连接,共ResponseSerialization中的response方法内部调用

    最终调用serializeResponseJSON方法来序列化数据。代码如下:

    public static func serializeResponseJSON(
        options: JSONSerialization.ReadingOptions,
        response: HTTPURLResponse?,
        data: Data?,
        error: Error?)
        -> Result<Any>
    {
        //代码省略
        do {
            let json = try JSONSerialization.jsonObject(with: validData, options: options)
            return .success(json)
        } catch {
            return .failure(AFError.responseSerializationFailed(reason: .jsonSerializationFailed(error: error)))
        }
    }
    
    • 这里就能看到我们熟悉的身影,通过JSONSerialization对数据做序列化处理
    • 根据序列化结构返回.success.failure

    以上方法的调用如下:

    public func response<T: DataResponseSerializerProtocol>(
        queue: DispatchQueue? = nil,
        responseSerializer: T,
        completionHandler: @escaping (DataResponse<T.SerializedObject>) -> Void)
        -> Self
    {
        delegate.queue.addOperation {
            let result = responseSerializer.serializeResponse(
                self.request,
                self.response,
                self.delegate.data,
                self.delegate.error
            )
            var dataResponse = DataResponse<T.SerializedObject>(
                request: self.request,
                response: self.response,
                data: self.delegate.data,
                result: result,
                timeline: self.timeline
            )
            dataResponse.add(self.delegate.metrics)
            (queue ?? DispatchQueue.main).async { completionHandler(dataResponse) }
        }
        return self
    }
    
    • 调用序列化方法,传入必要参数,对数据序列化处理,最终返回一个Result的枚举
    • 将序列化产生的枚举result封装至dataResponse中,此时序列化到响应就全都完成
    • 将结果通过闭包在主队列中向外发送

    三、Result

    是一个枚举,在response中传递的既是该枚举类型的变量,通过变量来判断数据请求是成功还是失败。

    .responseJSON { (response) in
        switch response.result {
            case .success(let json):
                print("json:\(json)")
                break
            case .failure(let error):
                print("error:\(error)")
                break
        }
    }
    

    只有json序列化之后才会有以上枚举变量,来通知业务层序列化成功还是失败。

    四、总结

    1、response在序列化器ResponseSerialization中初始化;
    2、序列化器实际上是Request类的扩展,方便通过闭包向业务层传递请求结果;
    3、序列化器的Request的扩展方法中都返回self,以便于链式调用;
    4、response帮助我们统一管理请求过程中的数据,请求成功、失败、时间轴等等,便于业务层处理;
    5、Response为不同请求类型,提供不同的结构体类型来管理数据。

    相关文章

      网友评论

          本文标题:Alamofire-Response

          本文链接:https://www.haomeiwen.com/subject/rnbhectx.html