我在 Angular 中使用 RxJS 有一个复杂的可观察链,并且我面临着嵌套 switchMap 和 docData 调用的意外行为。可观察链涉及使用 docData 使用附加用户数据丰富从 this.stream_service.readFeed() 获取的活动。但是,我在 docData 调用中遇到了意外行为,特别是使用
tap
和 switchMap
运算符。
我预计 docData next 和 mergeLatest next 日志只会出现一次,因为 Activity_response 数组中只有一项。
尽管有可观察到的发射值,tap 和 switchMap 运算符的记录次数比预期要多。 docData next 和combineLatest next 日志出现两次而不是一次。
这是代码:
private post_activity$ = toObservable(this.post).pipe(
// Use switchMap to switch to a new observable based on the latest value of post$
switchMap((post) => {
// Check if post is falsy (null, undefined, etc.)
if (!post) {
// If post is falsy, return an EMPTY observable (essentially a complete and empty observable)
return EMPTY;
}
// Call the current_user() function to get the current user
const current_user = this.current_user();
// Determine the feed_type based on whether the current user matches the post's user_id
const feed_type =
current_user && current_user?.uid === post.user_id ? 'user' : 'public';
// Return the result of calling this.stream_service.readFeed()
return this.stream_service.readFeed(
feed_type,
post.user_id,
1,
post.stream_activity_id
);
}),
tap((post_activity) => {
console.log('%cPost Activity', 'color: pink', post_activity);
}),
switchMap((activity_response) => {
// Check if activity_response is falsy
if (!activity_response) {
// If it is, return an EMPTY observable
return EMPTY;
}
// Call a service method to enrich the activities in activity_response
if (activity_response.length > 0) {
const activity = activity_response[0]; // 1 activity
console.log('Activity', activity); // This will log once
return docData(doc(this.firestore, 'users', activity.actor), {
idField: 'id',
}).pipe(
tap({
next: (user) => console.log('docData next', user),
error: (error) => console.log('docData error', error),
complete: () => console.log('docData complete'),
}), // this will log twice
switchMap((user: any) => {
const activity_user = {
username: user.username,
pronouns: user.pronouns,
avatar_url: user.avatar_url,
photo_url: user.photo_url,
};
return of({
user: activity_user,
activity: activity,
liked:
!!activity.own_reactions?.like &&
activity.own_reactions.like[0].user_id ===
this.user_service.current_user()?.uid,
});
}),
tap({
next: (activities) => console.log('combineLatest next', activities),
error: (error) => console.log('combineLatest error', error),
complete: () => console.log('combineLatest complete'),
}) // this will log twice too
);
} else {
return EMPTY;
}
}),
tap(() => {
this.count.set(this.count() + 1);
console.log('%cCount', 'color: lime', this.count()); // Count 2
})
);
可能导致可观察链中出现意外行为的原因以及如何确保 docData next 和 mergeLatest next 日志仅按预期出现一次?
任何有关调试和解决此问题的见解或指导将不胜感激。谢谢!
附加信息:
我添加了一些代码片段来检查隔离它是否会记录 docData() 两次。然而,我最终让事情变得更加令人费解,因为我发现 docData() 不仅只记录一次(如预期),而且我在 switchMap 中的代码也只记录一次。真是令人难以置信!
data$ = docData(
doc(this.firestore, 'users', activity.actor)
).pipe(
tap({
next: (user) => console.log('docData next', user),
error: (error) => console.log('docData error', error),
complete: () => console.log('docData complete'),
}) // this will log twice
);
private readonly data = toSignal(this.data$);
经过大量测试,我发现
siwtchMap
函数记录了两次。将其转换为 map
后,它现在仅记录一次。