Reputation: 6854
I have a method that returns the following observable.
class Service {
getData() {
// the select observable will fire on every form change
return this.store.select('filters').switchMap(filters => {
return this.http.get('call the api with the filters')
}).take(1);
}
}
In my component, I call this method on submit.
class Component {
submit() {
this.service.getData().subscribe(...)
}
}
The problem is that after I call submit once, I see two HTTP calls in the second submit. My question is if the take(1) operator, in this case, is killing both the inner and the outer observables?
Upvotes: 4
Views: 4627
Reputation: 63
Look at the following code:
readonly propertyA$ = new BehaviorSubject<string | null>('A');
readonly propertyB$ = new ReplaySubject<string[] | null>(1);
constructor(ref: ChangeDetectorRef) {
setTimeout(() => {
this.propertyB$.next(['B']);
}, 2000);
setTimeout(() => {
this.propertyB$.next(['B2']);
}, 3000);
setTimeout(() => {
this.propertyA$.next('A2');
}, 4000);
setTimeout(() => {
this.propertyB$.next(['B3']);
}, 5000);
setTimeout(() => {
this.propertyB$.next(['B4']);
}, 6000);
setTimeout(() => {
this.propertyA$.next('A3');
}, 7000);
setTimeout(() => {
this.propertyB$.next(['B5']);
}, 8000);
this.propertyA$.pipe(switchMap(propertyA => {
return this.propertyB$.pipe(
take(1), //and without
map(propertyB => ([propertyA, propertyB] as [string, string[]]))
)
})).subscribe(x => console.log('propertyA & propertyB (combineLatestFrom): ', x));
}
Without take(1):
A, B
A, B2
A2, B2
A2, B3
A2, B4
A3, B4
A3, B5
With take(1):
A, B
A2, B2
A3, B4
Upvotes: 0
Reputation: 96889
This is completely unrelated to the take()
operator. You're simply making two subscriptions to the same source Observable with two chains.
The take(1)
operator then just accepts only the first item emitted and send complete
notification.
Right now you have the following:
+-- switchMap --- take --> subscribe()
-- store --+
+-- switchMap --- take --> subscribe()
So the same value is pushed to two different chains with two different switchMap
's.
While you probably want something like this:
+--> subscribe()
-- store --- switchMap --+
+--> subscribe()
For example you have this (instead of do()
you have switchMap()
):
const subject = new Subject();
const obs = subject
.do(console.log);
obs.subscribe(i => console.log('next:', i));
obs.subscribe(i => console.log('next:', i));
subject.next(1);
... which prints the following. Notice that the do()
operator received two values:
1
next: 1
1
next: 1
Instead you could use:
const obs = subject
.do(console.log)
.publish()
.refCount();
or this ...
const multicast = new Subject();
const obs = subject
.do(console.log)
.subscribe(multicast);
multicast.subscribe(...);
or this ...
const obs = subject
.do(console.log)
.publish();
obs.connect();
or whatever depending on what you need.
This goes through just one do()
:
1
next: 1
next: 1
Upvotes: 2