文内介绍的是过滤操作符的一些实际使用场景.

额外介绍一些过滤操作符以及一些实际开发的做法, 包括如下:

  1. share 操作符

  2. filter 操作符

  3. 将老的异步代码转换为返回可观察序列

  4. takeLast 操作符

  5. take(_: scheduler:) 即只在固定时间段内取元素, 否则自动取消订阅.

  6. throttle 操作符: 在固定时间段内只取第一个元素.

代码如下所示:

swift
/*
 1. share 操作符
 如果不作处理的话, 每次针对某个 Observable 的订阅均会引起 Observable 调用 create. 且可能每次 create 时序列中的
 元素都和之前的不一样了.
 故可以使用 share 操作符来避免这种多余的 create 发生.
 share 操作符的原理是: 只有当订阅者的数量从 0 到 1 时才会调用 create. 如果之后的订阅者进来, share 则会提供之前已经创建
 好的订阅供它们使用.
 当所有的订阅都被释放后, share 也会将共享序列释放掉.
 这个操作符暂时没有例子.
 */

/*
 2. filter 操作符: 过滤效果和 swift 本身提供的类似.
 另外可以利用 filter 操作符来做一些额外的工作, 比如在判断的同时进行一些计算, 并将结果保存到对象的属性中.
 */
private func filterElem() {
    exampleOf(msg: "过滤操作符: filter", action: { bag in
        let obv = Observable.of(1, 3, 5, 7, 9, 2, 4, 6, 8, 10)
        obv.filter({ $0 % 2 == 0 }).subscribe(onNext: {
            print($0)
        }, onError: {
            print($0)
        }, onCompleted: {
            print("完成")
        }, onDisposed: {
            print("被释放")
        }).disposed(by: bag)
    })
}

/*
 3. 将老的异步代码转换为返回 Observable 或 Traits 或 Subject 的办法很简单:
 */
private func createAnObservable() {
    let observable = Observable<Data>.create({ observer in
        let disposeables = Disposables.create()
        let session = URLSession.shared
        session.dataTask(
            with: URL(string: "https://www.baidu.com")!,
            completionHandler: { data, resp, error in
                if let error = error {
                    observer.onError(error)
                }
                observer.onNext(data!)
                observer.onCompleted()
        }).resume()
        return disposeables
    })
    observable.subscribe(onNext: {
        print($0)
    }, onError: {
        print($0)
    }, onCompleted: {
        print("完成")
    }, onDisposed: {
        print("被释放")
    }).disposed(by: disposeBag)
}

/*
 4. takeLast 操作符: 不用再费劲心机想跳过多少多少个了, 直接取最后一个
 */
private func takeLastElem() {
    exampleOf(msg: "takeLast 操作符", action: { bag in
        let obv = Observable.of(1,2,3,4,5,6)
        obv.takeLast(1)
            .subscribe(onNext: {
                print($0)
            }, onError: {
                print($0)
            }, onCompleted: {
                print(" takeLast 的那个订阅完成")
            }, onDisposed: {
                print("释放 takeLast 订阅")
            }).disposed(by: bag)
    })
}

/*
 5. take(_: scheduler:) 在等待一段时机后自动结束某个订阅: 在网络操作下非常常见.
 通过下面这个例子可以发现, 停止订阅时正好间隔了 5 秒(时间在 μs 即微秒级别上有误差.)
 */
private func takeSomeTime() {
    let publish = PublishSubject<Void>()
    print("当前时间戳: \(Date().timeIntervalSinceReferenceDate)")
    publish.take(5.0, scheduler: MainScheduler.instance).subscribe(onNext: {
        print("发布了!")
        print("当前时间戳: \(Date().timeIntervalSinceReferenceDate)")
    }, onError: {
        print($0)
    }, onCompleted: {
        print("完成")
        print("当前时间戳: \(Date().timeIntervalSinceReferenceDate)")
    }, onDisposed: {
        print("被释放")
        print("当前时间戳: \(Date().timeIntervalSinceReferenceDate)")
    }).disposed(by: disposeBag)
    publish.onNext(())
}

/*
 6. throttle 操作符: 过滤掉指定时间段内的相邻元素, 即固定时间段内只取一个元素.
 这个操作符用来处理连续点击的情况非常有用.
 暂无示例.
 */