RxSwift)使用 flatMap 订阅可完成事件的问题

问题描述 投票:0回答:1
func someCompletable() -> Completable {
    return Completable.create { observer in
        observer(.completed)
        return Disposables.create()
    }
}
let buttonDidTap = PublishRelay<Void>()

buttonDidTap
    .debug()
    .subscribe()
    .disposed(by: disposeBag)

我看到在点击 buttonDidTap 时触发了 next() 事件。

但是,当我通过 flatMap 将其转换为 Completable 类型时,flatMap 之后没有发出任何事件。

buttonDidTap
    .flatMap { self.someCompletable() } 
    .debug()
    .subscribe()
    .disposed(by: disposeBag)

我也试过订阅所有事件 onNext、onCompletable、onError 和 onDisposed,但它们都没有发出。 知道这是为什么吗?

这是一个 gif 运行屏幕 :https://user-images.githubusercontent.com/57667738/229386647-c061d185-2015-40af-9150-5daac58c47ec.gif

buttonDidTap
    .debug() //onNext event fired
    .flatMap { self.someCompletable() } 
    .debug() //no event fired
    .subscribe()
    .disposed(by: disposeBag)

我的猜测是flatMap在将Completable转换为Observable的过程中失去了Completable的特性,还原为Observable的形式。 因此,对 onCompleted 的调用似乎消失了。 我该如何解决这个问题?

ios swift xcode rx-swift
1个回答
0
投票

flatMap
在它跟随的每个可观察对象完成之前无法完成。否则它将无法响应任何更多事件。例如,下次点击按钮时。

所以当 completable 发出一个 completed 事件时,flatMap 应该做什么?

  • 它不能发出下一个事件,因为可完成的没有发出下一个事件。
  • 它不能发出错误事件,因为没有错误。如果可完成的 did 发出错误,那么它可以。
  • 它无法发出已完成的事件,因为它仍在监视按钮点击以获取更多下一个事件。

出于这个原因,您看不到任何事件从 flatMap 中发出(直到链上游进一步发出错误或所有可完成的订阅可观察到的按钮点击已完成。)

如果您想知道可完成事件何时真正完成,您需要将已完成的事件转换为下一个事件。例如:

buttonDidTap
    .flatMap { someCompletable.andThen(Observable.just(())) }

这样,每次

.next(())
完成时,从 flatMap 返回的 observable 都会发出一个
someCompletable
事件。

另外

您发布的代码:

buttonDidTap
    .debug() //onNext event fired
    .flatMap { self.someCompletable() } 
    .debug() //no event fired
    .subscribe()
    .disposed(by: disposeBag)

可能有一个保留周期。由于传递给

flatMap
的闭包保留了
self
并且 disposeBag 由
self
保留。这意味着
self
切向保留自己。

要删除循环,请在闭包外部创建 Completable:

let completable = someCompletable()
buttonDidTap
    .debug() //onNext event fired
    .flatMap { completable } 
    .debug() //no event fired
    .subscribe()
    .disposed(by: disposeBag)

之所以可行,是因为每次订阅 Completable 时,它都会调用您传递给其构造函数的闭包。

© www.soinside.com 2019 - 2024. All rights reserved.