I read a lot about switchmap and its purpose but I did not see a lot of examples when it comes to subscribing to the new data. So I use a nested subscription in my Angular project and I wanted to ask you how to use switchmap properly in my example to understand the concept better.
Here my nested subscription:
this.sharedSrv.postDetail.subscribe(async post => {
if(post) {
this.hasPost = true;
this.post = post;
}
console.log(post);
this.viewedMainComment = null;
this.viewedSubComments = [];
this.userSrv.getUserAsObservable().subscribe(user => {
if(user){
if(this.post.user.id == user.id) this.isOwnPost = true;
this.user = user;
this.postsSrv.getPostInteraction(this.user.id, this.post.id, this.post.user.id).subscribe(interaction => {
this.hasSubscribed = interaction["hasSubscribed"];
this.wasLiked = interaction["wasLiked"];
this.wasDisliked = interaction["wasDisliked"];
this.hasSaved = interaction["hasSaved"];
});
console.log(user);
this.isLoggedIn = true
} else {
this.isLoggedIn = false;
}
})
})
How would I use switchmap correctly here? Any help is appreciated.
There are multiple things to notice here
this.sharedSrv.postDetail
and this.userSrv.getUserAsObservable()
are unrelated. In that case you could also use RxJS forkJoin
to trigger the observables in parallel. Since you've asked for switchMap
, you could try the followingimport { of } from 'rxjs';
import { switchMap } from 'rxjs/operators';
this.sharedSrv.postDetail.pipe(
switchMap(post => {
if (post) {
this.hasPost = true;
this.post = post;
}
console.log(post);
this.viewedMainComment = null;
this.viewedSubComments = [];
return this.userSrv.getUserAsObservable();
}),
switchMap(user => {
if (user) {
if (this.post.user.id == user.id) this.isOwnPost = true;
this.user = user;
console.log(user);
return this.postsSrv.getPostInteraction(this.user.id, this.post.id, this.post.user.id);
}
return of(null); // <-- emit `null` if `user` is undefined
})
).subscribe(
interaction => {
if(!!interaction) { // <-- only proceed if `interaction` is defined
this.hasSubscribed = interaction["hasSubscribed"];
this.wasLiked = interaction["wasLiked"];
this.wasDisliked = interaction["wasDisliked"];
this.hasSaved = interaction["hasSaved"];
this.isLoggedIn = true;
} else { // <-- set `isLoggedIn` to false if `user` was undefined
this.isLoggedIn = false;
}
}
);
async
. First I'd recommend you not to mix observables and promises unless absolutely necessary. Second you could use RxJS from
function to convert an observable to a promise.import { from, of } from 'rxjs';
import { switchMap } from 'rxjs/operators';
const obs$ = this.sharedSrv.postDetail.pipe(
switchMap(post => {
if (post) {
this.hasPost = true;
this.post = post;
}
console.log(post);
this.viewedMainComment = null;
this.viewedSubComments = [];
return this.userSrv.getUserAsObservable();
}),
switchMap(user => {
if (user) {
if (this.post.user.id == user.id) this.isOwnPost = true;
this.user = user;
console.log(user);
return this.postsSrv.getPostInteraction(this.user.id, this.post.id, this.post.user.id);
}
return of(null); // <-- emit `null` if `user` is undefined
})
);
from(obs$).then(
interaction => {
...
}
);