永远不要使用Swift的Combine返回平面图

时间:2019-10-18 13:34:55

标签: swift rx-swift combine

在RxSwift中,flatMap运算符可以轻松返回非完成的Observable。假设我们有一个(人为的和愚蠢的)可观察链:

let repo = DataRepository()

Observable
    .just(Int.random(in: 0 ..< 1000))
    .flatMap { num -> Observable<String> in
        if num == 42 {
            return .never()
        }

        return repo
            .fetchData()
            .filter { $0.statusCode == 200 }
            .map { $0.data.title }
    }

使用Combine,我能得到的最接近的东西是这样的(还没有尝试编译,但是你明白了):

Just(Int.random(in: 0 ..< 1000))
    .flatMap { num -> AnyPublisher<String, Never> in
        if num == 42 {
            return Empty<String, Never>(completeImmediately: false).eraseToAnyPublisher()
        }

        return repo
            .fetchData()
            .filter { $0.statusCode == 200 }
            .map { $0.data.title }
            .eraseToAnyPublisher()
    }

我对这个解决方案还可以,但是我想避免两个问题:

1)Combine解决方案在实现相同目标方面更为冗长。

2)我必须在两个返回的发布者上调用eraseToAnyPublisher(),否则返回类型不匹配。我相信调用eraseToAnyPublisher()会阻止Swift进行一些内部优化(我再也找不到关于此优化的文章了;关于此的信息很少)

有人能更好地处理这种情况吗?

1 个答案:

答案 0 :(得分:0)

尝试将任何条件逻辑引入运算符。

最好在过滤器中捕获发出类似Observable.never之类的条件,这样您就可以免费获得“从不”行为。

示例:

Just(Int.random(in: 0 ..< 1000))
        .filter { $0 != 42 }
        .flatMap {
            return repo
                .fetchData()
                .filter { $0.statusCode == 200 }
                .map { $0.data.title }
        }

我对DataRepository中的类型了解不多,无法知道是否需要在flatMap闭包内键入擦除。