Swift 使用斯威夫特联合收割机时,切勿在平面图中返回

Swift 使用斯威夫特联合收割机时,切勿在平面图中返回,swift,rx-swift,combine,Swift,Rx Swift,Combine,在RxSwift中,flatMap操作符可以很容易地返回一个不完整的可观测值。假设我们有一条精心设计的愚蠢的可观测链: let repo = DataRepository() Observable .just(Int.random(in: 0 ..< 1000)) .flatMap { num -> Observable<String> in if num == 42 { return .never()

在RxSwift中,flatMap操作符可以很容易地返回一个不完整的可观测值。假设我们有一条精心设计的愚蠢的可观测链:

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联合收割机解决方案在某种程度上更为冗长,以实现相同的目标

2我必须在两个返回的发布服务器上调用eraseToAnyPublisher,否则返回类型不匹配。我相信给出版商打电话会阻止斯威夫特应用一些内部优化,我再也找不到我读过的关于这种优化的文章了;这方面的信息很少


有谁有更好的方法来处理这个示例场景吗?

尝试将任何条件逻辑提升到运算符中

在什么条件下,你发出像Observable.never这样的东西,最好在过滤器中捕捉到,这样你就可以免费获得never行为

例如:

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

我对DataRepository中的类型了解不够,不知道是否需要在flatMap闭包中键入erase。

是的,我意识到这是一个选项,正如我所说,我的示例有点做作。您建议的方法在更高级的用例中不起作用。例如,当您有一个依赖于多个观察值的条件语句时,您不能使用简单的过滤器。在RxSwift中,您可以使用combineLatest并返回一个新的可观测值,或者如果不应发出任何信息,则返回一个“从不”,然后返回一个平面图。这就是我用Combine努力复制的东西,至少在不使用橡皮擦的情况下是这样。你可以在flatMap中使用值,在filter中使用值。我不知道为什么你不能在更高级的用例中使用filter。这样,您就不必在flatMap闭包中创建新的发布服务器,然后键入擦除它,这是您首先要防止的。如果flatMap中的逻辑没有像您提供的示例中那样解析为布尔值,然后使用适当的运算符并将结果平面映射。仅对发布者的输出进行操作,您永远不会进入创建新发布者的业务。在某些情况下,您可能希望这样做,例如,在给定结果上使用flatMap仅发出成功值。我在这里没有找到避免类型擦除的方法,尽管我在flatMap的结果上执行它,而不是在闭包中执行它,闭包仍然比Rx更详细。这是由具体实现构建的联合运算符的结果,Rx将它们隐藏在协议后面,并以这种方式获得类型擦除。没错,任何解析为布尔值的逻辑也可以放在过滤器中。我在评论中的意思是,依赖于多个变量的条件语句可以在CombineTest+flatMap中处理。如果我想在过滤器中应用条件逻辑,我必须做额外的工作:CombineTest必须映射到其参数的元组,过滤器必须执行逻辑,最后调用flatMap来完成通常在flatMap中直接完成的剩余工作。所以这也更冗长/混乱。首先。在这里,返回可观察的。从不是一个非常糟糕的主意。这样做的结果是,您的平面图将永远无法完成。最好是返回Observable.empty.Second,是的,您仍然需要删除任何发布服务器,您说该发布服务器将停止某些内部优化,但这是RxSwift甚至没有提供的优化,因此如果后者的性能可以接受,我相信前者也可以。