美文网首页
16.9常用的忽略事件操作符

16.9常用的忽略事件操作符

作者: CDLOG | 来源:发表于2019-07-17 18:08 被阅读0次

    在对RxSwift的基本概念有了一个比较全面的认识之后,在进一步开发App之前,我们要先积累更多RxSwift operators相关的知识。理解它们并不困难,你不必完全记住它们,但是至少要在心里留有印象。因为,对特定的事件序列使用正确的operator,是编写语义正确的Rx代码的重要基础。

    在这一节中,我们先来看如何忽略特定的事件。从忽略全部事件到自定义指定事件,RxSwift提供了多种operators。为了演示operators的用法,我们用SPM新建了一个RxSwift项目,并在Sources目录添加了两个文件:

    ignoring-ops-1

    其中,helper.swift中只定义了一个函数:

    func example(_ description: String,
        action: (Void) -> Void) {
    
        print("================== \(description) ==================")
        action()
    }
    
    

    它的作用有两个,一来,可以在任何测试代码执行前,打印一个提示方便我们观察结果;二来,action可以提供一个独立的scope,方便我们利用DisposeBag回收资源。

    而我们所有的演示代码,都会编写在main.swift里。

    Ignore elements

    第一个要介绍的operator是ignoreElements,它会忽略序列中所有的.next事件。我们用一个PublishSubject<String>来演示它的用法:

    example("ignoreElements") {
        let tasks = PublishSubject<String>()
        let bag = DisposeBag()
    
        tasks.subscribe { print($0) }
            .addDisposableTo(bag)
    
        tasks.onNext("T1");
        tasks.onNext("T2");
        tasks.onNext("T3");
        tasks.onCompleted();
    }
    
    

    这是一个标准的PublishSubject订阅,我们可以在控制台看到类似下面的结果:

    ignoring-ops-1

    如果我们要忽略掉所有的.next事件,只接受.completed事件,可以把之前的订阅代码改成这样:

    tasks.ignoreElements()
        .subscribe { print($0) }
        .addDisposableTo(bag)
    
    

    重新执行一下,就会看到下面的结果了:

    ignoring-ops-1

    用序列图把它画出来,就是这样的:

    ignoring-ops-1

    skip

    除了一次性忽略所有的.next之外,我们还可以选择忽略事件序列中特定个数的.next。例如,在我们的例子里,假设队列中前两个任务都是流水线上其它人完成的,而你只需要完成第三个任务,就可以这样:

    tasks.skip(2)
        .subscribe {
            print($0)
        }
        .addDisposableTo(bag)
    
    

    重新执行一下,就能看到下面的结果了:

    ignoring-ops-1

    其中,skip表示从事件序列中的第一个元素开始,忽略其参数指定个数的事件,用序列图表示,就是这样的:

    ignoring-ops-1

    skipWhile / skipUntil

    除了可以忽略指定个数的事件外,我们还可以通过一个closure自定义忽略的条件,这个operator叫做skipWhile。但它和我们想象中有些不同的是,它不会“遍历”事件序列上的所有事件,而是当遇到第一个不满足条件的事件之后,就不再忽略任何事件了。

    例如,为了忽略名称不等于T2事件,我们编写了下面的代码:

    tasks.skipWhile {
        $0 != "T2"
    }
    .subscribe {
        print($0)
    }
    .addDisposableTo(bag)
    
    

    但执行一下,却会看到这样的结果:

    ignoring-ops-1

    可以看到,skipWhile只忽略了T1,而没有忽略T3。而这就是While的含义,它只忽略到第一个不满足条件的事件,然后,就完成任务了。用序列图表示,就是这样的:

    ignoring-ops-1

    另外一个和skipWhile类似的operator是skipUntil,它不用一个closure指定忽略的条件,而是使用另外一个事件序列中的事件。例如,我们先把代码改成这样:

    let tasks = PublishSubject<String>()
    let bossIsAngry = PublishSubject<Void>()
    let bag = DisposeBag()
    
    tasks.skipUntil(bossIsAngry)
        .subscribe {
            print($0)
        }
        .addDisposableTo(bag)
    
    tasks.onNext("T1");
    tasks.onNext("T2");
    tasks.onNext("T3");
    tasks.onCompleted();
    
    

    执行一下就会看到,我们不会订阅到任何事件。这就是skipUntil的效果,它会一直忽略tasks中的事件,直到bossIsAngry中发生事件为止。把它用序列图表示出来,是这样的:

    ignoring-ops-1

    为了观察到这个效果,我们在T2T3之间添加下面的代码:

    tasks.onNext("T1");
    tasks.onNext("T2");
    bossIsAngry.onNext();
    tasks.onNext("T3");
    
    

    重新执行一下,就可以看到订阅T3的结果了。

    ignoring-ops-1

    distinctUntilChanged

    最后一个要介绍的,是通过distinctUntilChanged忽略序列中连续重复的事件。例如下面这个例子:

    example("ignoreElements") {
        let tasks = PublishSubject<String>()
        let bag = DisposeBag()
    
        tasks.distinctUntilChanged()
            .subscribe {
                print($0)
            }
            .addDisposableTo(bag)
    
        tasks.onNext("T1")
        tasks.onNext("T2")
        tasks.onNext("T2")
        tasks.onNext("T3")
        tasks.onNext("T3")
        tasks.onNext("T4")
        tasks.onCompleted()
    }
    
    

    由于T2T3都属于连续重复的事件,因此它们各自的第二次出现都会被忽略,我们只能订阅到下面这样的结果:

    ignoring-ops-1

    它的序列图是这样的:

    ignoring-ops-1

    但是,如果把T2放到两个T3中间,此时就没有任何连续重复的事件了,我们就会订阅到所有任务。

    What's next?

    以上,就是和忽略事件相关的operators,简单来说,就是从忽略全部(ignoreElements)、到忽略指定个数(skip(n))、再到忽略指定条件的事件(skipWhileskipUntil),最后是忽略连续重复的事件(distinctUntilChanged)。理解了它们之后,下一节,我们来看如何获取特定的事件。

    相关文章

      网友评论

          本文标题:16.9常用的忽略事件操作符

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