RxSwift(5)—— 高阶函数(上)

就问此时此刻还有谁?45度仰望天空,该死!我这无处安放的魅力!


RxSwift目录直通车--- 和谐学习,不急不躁!


这一篇文章继续上一篇:RxSwift-高阶函数(上)给大家介绍 RxSwift 非常重要的高阶函数,也不多说,开始介绍

5:从可观察对象的错误通知中恢复的操作符

5.1:catchErrorJustReturn

  • 从错误事件中恢复,方法是返回一个可观察到的序列,该序列发出单个元素,然后终止
print("*****catchErrorJustReturn*****")
let sequenceThatFails = PublishSubject<String>()

sequenceThatFails
    .catchErrorJustReturn("Cooci")
    .subscribe { print($0) }
    .disposed(by: disposeBag)

sequenceThatFails.onNext("Hank")
sequenceThatFails.onNext("Kody") // 正常序列发送成功的
//发送失败的序列,一旦订阅到位 返回我们之前设定的错误的预案
sequenceThatFails.onError(self.lgError) 

5.2:catchError

  • 通过切换到提供的恢复可观察序列,从错误事件中恢复
print("*****catchError*****")
let recoverySequence = PublishSubject<String>()

sequenceThatFails
    .catchError {
        print("Error:", $0)
        return recoverySequence  // 获取到了错误序列-我们在中间的闭包操作处理完毕,返回给用户需要的序列(showAlert)
    }
    .subscribe { print($0) }
    .disposed(by: disposeBag)

sequenceThatFails.onNext("Hank")
sequenceThatFails.onNext("Kody") // 正常序列发送成功的
sequenceThatFails.onError(lgError) // 发送失败的序列

recoverySequence.onNext("CC")

5.3:retry

  • 通过无限地重新订阅可观察序列来恢复重复的错误事件
print("*****retry*****")
var count = 1 // 外界变量控制流程
let sequenceRetryErrors = Observable<String>.create { observer in
    observer.onNext("Hank")
    observer.onNext("Kody")
    observer.onNext("CC")
    
    if count == 1 { 
        // 流程进来之后就会过度-这里的条件可以作为出口,失败的次数
        observer.onError(self.lgError)  // 接收到了错误序列,重试序列发生
        print("错误序列来了")
        count += 1
    }
    
    observer.onNext("Lina")
    observer.onNext("小雁子")
    observer.onNext("婷婷")
    observer.onCompleted()
    
    return Disposables.create()
}

sequenceRetryErrors
    .retry()
    .subscribe(onNext: { print($0) })
    .disposed(by: disposeBag)

5.4:retry(_:):

  • 通过重新订阅可观察到的序列,重复地从错误事件中恢复,直到重试次数达到max未遂计数
print("*****retry(_:)*****")
let sequenceThatErrors = Observable<String>.create { observer in
    observer.onNext("Hank")
    observer.onNext("Kody")
    observer.onNext("CC")
    
    if count < 5 { // 这里设置的错误出口是没有太多意义的额,因为我们设置重试次数
        observer.onError(self.lgError)
        print("错误序列来了")
        count += 1
    }
    
    observer.onNext("Lina")
    observer.onNext("小雁子")
    observer.onNext("婷婷")
    observer.onCompleted()
    
    return Disposables.create()
}

sequenceThatErrors
    .retry(3)
    .subscribe(onNext: { print($0) })
    .disposed(by: disposeBag)

6:Rx流程操作符。

6.1:debug

  • 打印所有订阅、事件和处理。
print("*****debug*****")
var count = 1

let sequenceThatErrors = Observable<String>.create { observer in
    observer.onNext("Hank")
    observer.onNext("Kody")
    observer.onNext("CC")
    
    if count < 5 {
        observer.onError(self.lgError)
        print("错误序列来了")
        count += 1
    }
    
    observer.onNext("Lina")
    observer.onNext("小雁子")
    observer.onNext("可心")
    observer.onCompleted()
    
    return Disposables.create()
}

sequenceThatErrors
    .retry(3)
    .debug()
    .subscribe(onNext: { print($0) })
    .disposed(by: disposeBag)

6.2: RxSwift.Resources.total:

  • 提供所有Rx资源分配的计数,这对于在开发期间检测泄漏非常有用。
print("*****RxSwift.Resources.total*****")

print(RxSwift.Resources.total)

let subject = BehaviorSubject(value: "Cooci")

let subscription1 = subject.subscribe(onNext: { print($0) })

print(RxSwift.Resources.total)

let subscription2 = subject.subscribe(onNext: { print($0) })

print(RxSwift.Resources.total)

subscription1.dispose()

print(RxSwift.Resources.total)

subscription2.dispose()

print(RxSwift.Resources.total)

7:链接操作符

7.1:multicast

  • 将源可观察序列转换为可连接序列,并通过指定的主题广播其发射。
func testMulticastConnectOperators(){
    print("*****multicast*****")
    let subject = PublishSubject<Any>()
    subject.subscribe{print("00:\($0)")}
        .disposed(by: disposeBag)
    
    let netOB = Observable<Any>.create { (observer) -> Disposable in
            sleep(2)// 模拟网络延迟
            print("我开始请求网络了")
            observer.onNext("请求到的网络数据")
            observer.onNext("请求到的本地")
            observer.onCompleted()
            return Disposables.create {
                print("销毁回调了")
            }
        }.publish()
    
    netOB.subscribe(onNext: { (anything) in
            print("订阅1:",anything)
        })
        .disposed(by: disposeBag)

    // 我们有时候不止一次网络订阅,因为有时候我们的数据可能用在不同的额地方
    // 所以在订阅一次 会出现什么问题?
    netOB.subscribe(onNext: { (anything) in
            print("订阅2:",anything)
        })
        .disposed(by: disposeBag)
    
    _ = netOB.connect()
}
  • 底层逻辑探索中间变量ConnectableObservableAdapter保存了源序列source中间序列makeSubject
  • 订阅流程self.lazySubject.subscribe(observer)一个懒加载的序列,保证了中间变量ConnectableObservableAdapter每一次都是同一个响应序列
  • 剩下就是PublishSubject的订阅效果
  • 完事等待源序列的响应,但是我们的源序列的订阅是在connect函数里面!如果没有调用connect函数,意味着就永远不会发送响应。这样背后的逻辑就是,前面所以的发送响应在connect函数之前的都没有任何的意义!
  • 以上也就说明了我们的publish就是状态共享的:connnect一次我们序列发送一次响应(响应所有订阅)。

7.2:replay

  • 将源可观察序列转换为可连接的序列,并将向每个新订阅服务器重放以前排放的缓冲大小
  • 首先拥有和publish一样的能力,共享 Observable sequence, 其次使用replay还需要我们传入一个参数(buffer size)来缓存已发送的事件,当有新的订阅者订阅了,会把缓存的事件发送给新的订阅者
func testReplayConnectOperators(){   
    print("*****replay*****")

    let interval = Observable<Int>.interval(.seconds(1), scheduler: MainScheduler.instance).replay(5)
    
    interval.subscribe(onNext: { print(Date.time,"订阅: 1, 事件: \($0)") })
        .disposed(by: self.disposeBag)
    
    delay(2) { _ = interval.connect() }
    
    delay(4) {
        interval.subscribe(onNext: { print(Date.time,"订阅: 2, 事件: \($0)") })
            .disposed(by: self.disposeBag)
    }
    
    delay(8) {
        interval.subscribe(onNext: { print(Date.time,"订阅: 3, 事件: \($0)") })
            .disposed(by: self.disposeBag)
    }
    delay(20, closure: {
        self.disposeBag = DisposeBag()
    })
    
    /**
     订阅: 1, 事件: 4
     订阅: 1, 事件: 0
     2019-05-28 21-32-42 订阅: 2, 事件: 0
     2019-05-28 21-32-42 订阅: 1, 事件: 1
     2019-05-28 21-32-42 订阅: 2, 事件: 1
     2019-05-28 21-32-45 订阅: 2, 事件: 4
     2019-05-28 21-32-46 订阅: 3, 事件: 0
     2019-05-28 21-32-46 订阅: 3, 事件: 1
     2019-05-28 21-32-46 订阅: 3, 事件: 2
     2019-05-28 21-32-46 订阅: 3, 事件: 3
     2019-05-28 21-32-46 订阅: 3, 事件: 4
     
     // 序列从 0开始
     // 定时器也没有断层  sub2 sub3 和 sub1 是同步的
     */
}

高阶函数的用法还是有点意思的!如果你是一个RxSwift新手,还是非常建议大家耐着性子好好练习,对你的开发绝对有帮助!

就问此时此刻还有谁?45度仰望天空,该死!我这无处安放的魅力!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343

推荐阅读更多精彩内容