RxSwift实战Swift开发

Swift-自己封装一个网络请求,基于Rxswift、Moya、

2019-03-25  本文已影响17人  Fisland_枫

近来项目需求,需要用到了Rxswift和Moya,但是网上很多例子Moya都是基于Mapper封装,而Mapper的创建的代码实在有点多,而且Swift4.0新特性之一就是官方自己出的JSON解析-Codable,那么我们就用起来吧。
由于篇幅问题,Codable具体使用不在这里赘述

核心代码

主要是封装Moya的provider

    /// 默认rx请求
    ///
    /// - Parameters:
    ///   - api: api
    ///   - type: 解析类型
    /// - Returns: 返回数据或错误
    public static func rxRequest<T:Codable>(_ api :MultiTarget, type:T.Type) -> Single<T>{

        let decoder = CleanJSONDecoder()
        return self.provider.rx.request(api)
            .asObservable()
            .take(1)
            .filterSuccess()
            .map(type, using: decoder)
            .observeOn(MainScheduler.instance)
            .asSingle()
    }
  1. 其中take(1)是保证该信号只执行一次,避免了多次请求的问题
  2. moya也对codable做了分装,需要调用其对应方法就可以
  3. filterSuccess,在这个方法中主要对错误进行统一处理,每个公司可能都每个公司自己的数据定义,这里也只是作为参考
    public func filterSuccess() -> Observable<E> {
        return flatMap { (response) -> Observable<E> in
            
            let json = try JSON(response.mapJSON())
            //这里的情况是,只有code为0的时候,数据data才有东西
            if json.dictionaryValue["code"]?.intValue == 0{
                //code为0,表示成功
                return Observable.just(response)
            }
            //抛出错误
            if let errormodel = try? JSONDecoder().decode(ErrorResponse.self, from: json.rawData()){
                return Observable.error(HTTPServiceError.logic(err: errormodel))
            }
            return  Observable.error(MoyaError.jsonMapping(response))

        }
    }

具体调用

        //获取语言
        let api = MultiTarget(TestAPI.language)
        //返回的是信息流 Single的
        JFHTTPService.rxRequest(api, type: Languages.self).subscribe(onSuccess: { (languages) in
            print(languages)
        }) { (error) in

        }.disposed(by: rx.disposeBag)
        
        
        //获取频道 channel
        let doubanList = MultiTarget(DouBanAPI.channels)
        JFHTTPService.rxRequestData(doubanList, with: "channels", type: [Channel].self).subscribe(onSuccess: { [weak self](list) in
            guard let self = self else{ return }
            self.dataSource = list
            self.table.reloadData()
            print(list)
        }) { (error) in
            
        }.disposed(by: rx.disposeBag)
  1. 其中api使用MultiTarget,这样可以项目内使用多个target达到组件化,不用所有的请求都在一个文件,GitHub demo中有具体使用
  2. 返回的是Single的流数据,可以对应该信号,再做别的操作,例如重试(retry)、合并(flatMap)、Map处理等等
  3. 传入的可以是该model的类型(model.self)或者是数组的类型([model].self)

举个例子

GitHub例子
Demo

上一篇下一篇

猜你喜欢

热点阅读