While trying to normalize data before combining it in a new stream, changes did not occur.
I want to check if the post is liked by the user through a Promise function before returning it to the Posts Observable.
this.data$ = combineLatest([
// stream 1 - posts
this.posts_service.posts$ as Observable<Post[]>,
// stream 2 - user
this.user_service.user$ as Observable<_User>,
]).pipe(
map(([posts, user]) => {
// if there is a user, check if they have liked the post
if (user) {
// check if user has liked post
posts = posts.map((post) => {
// send post and user id to a promise function that will return a boolean
this.posts_service.hasLikedPost(post, user.uid).then((has_like) => {
console.count('hasLikedPost');
post.has_like = has_like;
});
return post;
});
user = user;
console.table(posts);
return { posts, user };
} else {
return { posts };
}
})
);
}
CodePudding user response:
Here is my refactor. I extracted some functionality to separate function or method getPosts
just for cleaner code.
// Typing the property for better readability and type checking
const data$: Observable<{ posts: Post[], user: _User; }> = combineLatest([
// stream 1 - posts
this.postsService.posts$ as Observable<Post[]>,
// stream 2 - user
// assuming that user$ emits at least once, even there is no user
this.userService.user$ as Observable<_User>,
]).pipe(
// if there is a user, check if they have liked the post
switchMap(([posts, user]) => user ? getLikes(posts, user) : of({ posts })),
);
function getLikes(posts: Post[], user: _User): Observable<{ posts: Post[], user: _User; }> {
// create event from each post because we need to check asynchronously each one post for "has_like" flag
return from(posts).pipe(
// check each post if it is liked by user and add property to one
concatMap(post => from(this.postsService.hasLikedPost(post, user.uid))
.pipe(
map(hasLike => ({ ...post, hasLike }))
)
),
// merge back all the posts into array
toArray(),
// DEBUG
tap(posts => console.table(posts)),
// add user to replay
map(posts => ({ posts, user })),
);
}