Reputation: 17
I have a backend method called LikeExists() to verify if a certain user has liked a certain post.
public async Task<bool> LikeExists(int postId)
{
var post = await _postRepository.GetPostByIdAsync(postId);
var user = await _userRepository.GetUserByUsernameAsync(User.GetUsername());
if (_context.Likes.Where(i => i.PostId == post.Id && i.UserId == user.Id).FirstOrDefault() != null) return true;
return false;
}
The method works fine in Postman, but it does not do the job in Angular. If a user presses a like button I first want to check if this user has already liked this post. If he has, he will unlike it and the like will be deleted from the database. If he hasn't liked it, he will like it and the like will be saved in the database.
likeExists(){
this.postService.likeExists(this.post.id).subscribe((response: boolean) =>{
this.like = response;
});
}
likePost() {
if(this.likeExists){
this.postService.likePost(this.post.id, this.model).subscribe((response: Like) => {
this.likee = response;
console.log(response);
this.toastr.success('Liked');
}, error => {
console.log(error);
this.toastr.error(error.error);
});
} else {
this.postService.deleteLike(this.post.id).subscribe(() => {
this.toastr.success('Unliked');
}, error => {
console.log(error);
})
}
}
The problem is it always enters the if{} clause and never the else{} clause. The method below returns an Observable. I think the problem is that it must return a boolean. How can I make this work?
This is the method in the postService:
likeExists(postId: number) {
return this.http.get(this.baseUrl + 'like/exists/' + postId);
}
Upvotes: 0
Views: 185
Reputation: 2217
Try avoiding nested subscription since it will result in an unreadable and hard to maintain code, use rxjs pipes with operators instead, try something like this:
let id= this.post.id;
let likeExists$ = this.postService.likeExists(id);
likeExists$
.pipe(
switchMap(likeExists => {
if (likeExists) {
// delete like
return this.postService.deleteLike(id);
}
// otherwise addlike
return this.postService.addLike(id);
})
).subscribe(
res=> this.toastr.success('Success'),
err=> this.toastr.error('Failed')
);
or even shorter
let id= this.post.id;
let likeExists$ = this.postService.likeExists(id);
likeExists$
.pipe(switchMap(
liked => liked ? this.postService.deleteLike(id) : this.postService.addLike(id)}))
.subscribe(
res=> this.toastr.success('Success'),
err=> this.toastr.error('Failed')
);
Upvotes: 1
Reputation: 2273
The problem is that this.http.get
is asynchronous, which means that likeExists
returns before this.like
is being set. You need to wait for the value to be returned in your observable. Refactor your code to something along these lines:
likePost() {
// Check to see if like exists and wait for response from server
this.postService.likeExists(this.post.id).subscribe((response: boolean) => {
this.like = response;
if (this.like) {
this.postService.likePost(this.post.id, this.model).subscribe((response: Like) => {
this.likee = response;
console.log(response);
this.toastr.success('Liked');
}, error => {
console.log(error);
this.toastr.error(error.error);
});
} else {
this.postService.deleteLike(this.post.id).subscribe(() => {
this.toastr.success('Unliked');
}, error => {
console.log(error);
})
}
});
}
Also, this is a nice guide to asynchronous concepts in general. And the RxJS docs have a bunch of helpful information to get started.
Upvotes: 0