How Can I use the Bind Method in RXSwift? - rx-swift

The following sample code throws an error stating
No exact matches in call to instance method 'bind'
How can I bind the onNext of my publish subject to my observable?
let publish = PublishSubject<Void>()
// Error Here
publish.bind(to: myMethod())
func myMethod() -> Observable<Void> {
return Observable.create{ observer in
observer.onNext(())
observer.onCompleted()
return Disposables.create()
}
}

So what I want is everytime my publish subject emits an onNext event I want to trigger the observable of 'myMethod'
I'm not sure how to interpret this, but it sounds like you want something like:
let publish = PublishSubject<Void>()
let response = publish.flatMap { myMethod() }
response
.bind(onNext: { print($0) })
func myMethod() -> Observable<Void> {
Observable.create{ observer in
observer.onNext(())
observer.onCompleted()
return Disposables.create()
}
}
But it all seems rather pointless since all myMethod() does is emit a next event.

First, the bind(to:) method is in the RxCocoa Framework so you need to add import RxCocoa in your file.
Then, the observable created by myMethod will only be able to emit the event from the .create block. You can't use bind on it. If you need an observable with both the events from your subject and from the myMethod observable, you can do that :
let thirdObservable = Observable.merge(publish, myMethod())

Related

RxJS Is Observer and Subscriber the same thing?

From this documentation:
RxJS introduces Observables, a new Push system for JavaScript. An Observable is a Producer of multiple values, "pushing" them to Observers (Consumers).
Subscribing to an Observable is analogous to calling a Function.
To invoke an Observable we should call the subscribe() function from the Observable object itself and pass the observer as the consumer of the data delivered by the observable like:
observable.subscribe( { /*this is an observer*/ } );
Also this documentation says:
What is an Observer? An Observer is a consumer of values delivered by an Observable. Observers are simply a set of callbacks, one for each type of notification delivered by the Observable: next, error, and complete. The following is an example of a typical Observer object:
On the other hand the first documentation says:
The Observable constructor takes one argument: the subscribe function.
The following example creates an Observable to emit the string 'hi' every second to a subscriber.
import { Observable } from 'rxjs';
const observable = new Observable(function subscribe(subscriber) {
const id = setInterval(() => {
subscriber.next('hi')
}, 1000);
});
When calling observable.subscribe with an Observer, the function subscribe in new Observable(function subscribe(subscriber) {...}) is run for that given subscriber. Each call to observable.subscribe triggers its own independent setup for that given subscriber.
So the entity Subscriber is just the argument passed into the subscribe function when creating a new Observable? If not who is the subscriber?
Are Observers and Subscribers the same entity? as mentioned in this documentation
Why isn't the code that invokes observable.subscribe({observer as call backs}) the subscriber of the observable? Like the consumer of a function's return value is the code that makes the function call.
COMPLETE DESIGN PATTERN EXPLANATION
Observer
const observer = {
next: v => /* code for next callback*/,
error: err => /* code for error callback*/,
complete: () => /* code for completion callback*/
}
Subscription
const subscription = {
unsubscribe: () => /* code for unsubscribe callback */
}
Observable
const observable1 = from([1,2,3,4,5]);
const observable2 = of(1,2,3,4,5);
const observable3 = new Observable(observer => {
observer.next(1);
observer.next(2);
observer.next(3);
observer.next(4);
observer.next(5);
observer.complete();
return { // return a subscription
unsubscribe: () => /* code for unsubscribe callback */
};
});
Subscribe and use the Returned Subscription
// Store a subscription
const subscription = observable3.subscribe(observer);
// Invoke the unsubscribe callback defined by the observable.
subscription.unsubscribe();
Okay. Then What is a Subscriber?
[Subscriber] Implements the Observer interface and extends the Subscription class. While the Observer is the public API for consuming the values of an Observable, all Observers get converted to a Subscriber... Subscriber is a common type in RxJS, and crucial for implementing operators, but it is rarely used as a public API.
Are observers and subscribers the same thing? Kind of, yes? Depends on how concretely you ask the question.
Consider this:
observable3.subscribe({
next: v => /* code for next callback */
});
obsevable3.subscribe(
v => /* code for next callback */
);
The first is an object with only one observer property defined. The second is simply a lambda function. They both end up generating basically the same subscriber.

How can I subscribe and unsubscribe using onResume() and onPause() methods with RxJava 2?

Well, I need to bind emitting to my activity's lifecycle. How can I do that? And when should I create observer and observable instances?
If you have an observable that you want data from sometimes and not at other times, there is a simple way to subscribe and unsubscribe using the switchMap() operator.
Let's say you have an observable that want data from:
Observable<LocationData> locationDataObservable;
Then, if you introduce a switching observable:
PublishSubject<Boolean> switchObservable = PublishSubject.create();
you can control the subscriptions to the first observable:
Observable<LocationData> switchedLocationDataObservable =
switchObservable
.switchMap( abled -> abled ? locationDataObservable : Observable.never() )
.subscribe();
To enable receiving the data, perform
switchObservable.onNext( Boolean.TRUE );
and to disable,
switchObservable.onNext( Boolean.FALSE );
The switchMap() operator takes care of subscribing and unsubscribing for you.
It can be solved without Observable.never(). Just use BehaviourSubject with takeUntil and repeatWhen operators.
private fun getPauseUpdatesSource(): Flowable<Unit> {
return setUpdatesPausedSubject
.filter { it }
.map { }
.toFlowableLatest()
}
private fun getResumeUpdatesSource(): Flowable<Unit> {
return setUpdatesPausedSubject
.filter { it.not() }
.map { }
.toFlowableLatest()
}
And in the rx chain:
locationDataObservable
.takeUntil(getPauseUpdatesSource())
.repeatWhen { it.switchMap { getResumeUpdatesSource() } }
It just pauses your chain and doesn't emit any empty observables

startWith() that returns Subject

I want to emit values using Subject with default value.
startWith("def") is the method for this.
subject = new Rx.Subject().startWith("def value");
unfortunately startWIth returns Observable and therefore I cannot use onNext(), which is the sole reason I am using Subject in the first place. What is the workaround for this problem?
subject.onNext("next val"); //cannot call onNext, it is not a function of Observable
Just keep track of both the observable and the subject. I usually do something like...
export class FooService {
private _foos: Subject<Foo> = new subject<Foo>();
public get foos: Observable<Foo> {
return this._foos.startsWith(...);
}
public emitFoo(foo: Foo) {
this._foos.next(foo);
}
}
Your question isn't entirely clear. If you want all observers to see "def value" before anything else, then use #Pace's answer.
But if you want all observers to start with "the most recently emitted value", and use "def value" if they subscribe before you emit the first value, then use a BehaviorSubject:
var subject = new BehaviorSubject("default val");
subject.subscribe(...); // sees "default val", then anything you emit.
subject.next("foo");
subject.subscribe(...); // sees "foo", then anything else you emit (does not see "default val")

Why don't we need to subscribe to an observable here before converting it to a Promise?

My Service class contains code as :
Service.ts
//all imports are done
#Injectable()
export class Service{
constructor(private http: Http) { }
getGoogle():Observable<any> {
console.log("Inside service");
return this.http.get('https://jsonplaceholder.typicode.com/posts/1');
}
}
My page component where I make use of service.
Page.ts
//all imports are done
export class Page1{
constructor(private service: Service, private navCtrl: NavController) { }
async get() {
console.log("inside get method");
const data = await this.service.getGoogle().toPromise();
console.log('The response is' , data);
}
}
I have got the required result, but as to understand the concept of Observables and Observer, my Observable should have an Observer sitting to subscribe.Then why should'nt the code const data = await this.service.getGoogle.subscribe().toPromise() does not work here and shows error that property toPromise() does not exists on type Subscription.
I saw the official resource of toPromise() where I found that it is used with .just().toPromise().Then I found .just() API which states that
The just() method emits its parameter(s) as OnNext notifications, and
after that, it emits an OnCompleted notification.
So It is using the features of subscribe here then why it is not used with .subscribe()?
To get the values from an observable, you'll subscribe() on the observable. This starts the observable and it will send you the values it produces.
If you rather want to use a Promise you can call toPromise() on the observable instead. This will make the observable behave like a regular promise.
Under the covers, toPromise() calls subscribe() on the observable and waits for it to send complete(). When the complete() signal is received, the promise will resolve the last emitted next() signal.
toPromise() looks a bit like this:
myObservable.takeLast().subscribe(value => resolve(value));

RxSwift: how to have one observable trigger another one?

Suppose I have observable A, and I am trying to create observable B that emits two events: the first when A emits an event, and the second 5 seconds later.
So far I have the following:
self.B = Observable.create { [unowned self] observer in
self.A.subscribe(onNext: {
observer.onNext(0)
self.delay(5) {
observer.onNext(1)
}
})
return Disposables.create()
}
This works, but I feel uncomforatble subscribing to A from a closure. Is there a nicer way to do it?
Thanks!
The solution is to reuse the a observable for the delayed observable. Below is the code to do it, along with a proof of concept.
let a = button.rx.tap.asObservable()
let delay = a.delay(5.0, scheduler: MainScheduler.instance)
let b = Observable.of(a, delay).merge()
b.subscribe(onNext: {
print("foo")
}).disposed(by: bag)

Resources