[RxSwift] - observe(on:) vs. subscribe(on:) : when to use them to specify threads
23 Aug 2023 |
Summary
🔑 observe(on:)
: to set which scheduler (thread) you want to receive events on and use them.
🔑 subscribe(on:)
: to set where the observable does its work.
One of the confusing operations when using RxSwift is determining whether to use observe(on:)
or subscribe(on:)
. It is not difficult to decide, but it is something easy to get confused about, and I often forget and have to look it up most of the time.
Both of these are operators in Swift that allow you to set which thread (or scheduler) you would like your operation to run on. As you may know, specifying which thread, typically between the main and background threads, is a crucial task in iOS development.
Preliminary Concepts
Subscription
A subscription is created at the moment the .subscribe()
operator is called on an Observable. When you call .subscribe(onNext: …)
, what you create is a subscription. It is the act of subscribing - here is my observer, so please notify me when new events occur in the observable.
Observer
In .subscribe(onNext, onError…)
, an observer refers to the set of callbacks that define how to handle or react to each type of event in the event handler.
On the whole, subscription and observer are not exclusive concepts but are related.
Summary
- Observer: An “observer” is essentially a set of callbacks that define how to react to events emitted by an Observable.
- Subscription: A “subscription” refers to the action or process of an observer subscribing to an Observable’s emitted events.
Observable.just("Hello")
.subscribe(onNext: { value in // The callback passed to onNext is the observer
print("Received value: \\(value)")
})
// This call creates a subscription, and with the returned disposable,
// you can also cancel the subscription.
observe(on:) & subscribe(on:)
observe(on:)
: Specifies the thread on which the observer will be executed.subscribe(on:)
: Specifies the thread on which the subscription is created.
To put it simply:
observe(on:)
is where the code that handles (reacts to) the events is executed.subscribe(on:)
is where the Observable performs its work (generates events, etc.).
Observable<String>.create { observer in
// This runs on the background thread
print("Doing work on thread: \\(Thread.current)")
observer.onNext("Some Value")
return Disposables.create()
}
.subscribe(on: ConcurrentDispatchQueueScheduler(qos: .background))
.observe(on: MainScheduler.instance)
.subscribe(onNext: { value in
// This runs on the main thread
print("Received value on thread: \\(Thread.current)")
print("Received value: \\(value)")
})
- The Observable is created and works on the background queue because
subscribe(on:)
specifies the ConcurrentDispatchQueueScheduler. (the orange color part) - The observer handles the events on the main thread because
observe(on:)
specifies the MainScheduler. (the blue color part)