In my Swift UIViewController, I'm attempting to subscribe to a class member of type Variable, run it through a flatMapLatest call, and then have the onCompleted() call in the flatMapLatest observable execute on all subscribers. However, while onNext() is called, onCompleted() never is and I'm not sure why.
My class member is defined as:
private let privateVar = Variable<String>("")
while in my viewDidLoad() method, I set up the observables:
let localVar = self.privateVar.asObservable().distinctUntilChanged()
localVar.subscribe(onNext: { [weak self] sent in print("first onNext called") })
.disposed(by: self.disposeBag)
let mappedVar = localVar.flatMapLatest { self.ajaxLoad(var1: $0) }.share()
mappedVar.subscribe(
onNext: { [weak self] queryRes in
print("onNext called!")
},
onCompleted: { [weak self] in
print("onCompleted called!")
}
)
.disposed(by: self.disposeBag)
and my ajaxLoad method:
func ajaxLoad(var1 myVar: String) -> Observable<QueryResponse> {
return Observable.create { observable in
apollo.fetch(query: MyQuery()) { (result, _) in
observable.onNext(result?.data?.myQuery)
observable.onCompleted()
}
return Disposables.create()
}
}
I'm fairly new to ReactiveX so I may be a little hazy on what the Rx lifecycle actually looks like. Why might onNext be called in the flatMapLatest call, but not onCompleted? Any help would be appreciated. Thanks in advance!
The flatMap
operator does not emit completed events of any observable that you return inside the block.
The following code illustrates this clearly. .just(_)
emits the element and then a completed event, which does not terminate to subscription.
_ = Observable<Int>.interval(1, scheduler: MainScheduler.instance)
.debug("before flatmap")
.flatMap { .just($0 * 2) }
.debug("after flatmap")
.subscribe()
In fact, Variable
only emits completed when deallocated. See source v4.0 . Note that Variable is deprecated in RxSwift 4, you are encouraged to use RxCocoa's similar BehaviorRelay
instead.
deinit {
_subject.on(.completed)
}
Since you said you are new and a "little hazy"...
Keep in mind that whenever localVar
changes, it emits a new value and ajaxLoad(var1:)
gets called. The result of ajaxLoad(var1:)
then gets pushed to your subscribe's onNext closure.
Also keep in mind that if an Observable emits a .completed
it's dead. It can no longer emit anything else.
So flatMapLatest
can't complete (unless its source completes.) If it did, it would kill the whole pipe and no more changes to localVar
would get routed through the pipe, ajaxLoad(var:1)
wouldn't get called again with the new value and nothing more would get pushed to the subscribe's onNext method.
A sequence of observables can be thought of like a Rube Goldberg machine where a completed
shuts down the machine and an error
breaks it. The only time you should shut down the machine is if the source (in this case localVar
) is finished emitting values or the sink (destination, in this case the onNext: closure) doesn't want any more values.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.