angular - ngrx 文档参考分辨率
问题描述
我尝试使用ngrx 和firestore 来实现一个朋友系统。
因此,我创建了一个包含/users
用户信息的集合,例如姓名、头像图片链接、在线状态等。第二部分由/users/{id}/buddies
每个用户的集合组成,其中包含仅包含朋友的朋友信息
- 用户标识
- 好友状态,可以是:
pending
requested
或buddy
。 - 参考用户文档
此设置允许为每个用户朋友收集最少的集合,而无需跟踪buddies
表中用户信息的副本。
设置和上下文就这么多。
我在解决个人朋友的用户文档参考方面遇到了很多问题......理想情况下,我希望拥有一个好友商店,其中包含当前用户的所有好友,并且可以使用各种选择器进行选择。
Buddy 模型应该类似于:
export interface Buddy {
uid: string;
buddyStatus: BuddyStatus;
userRef: User | any;
}
User
模型如下所示:
export enum AuthState {
LOGGED_IN = "LOGGED_IN",
NOT_LOGGED_IN = "NOT_LOGGED_IN"
};
export interface User {
uid: string | null;
displayName: string | null;
authState: AuthState;
loading?: boolean;
error?: string | null;
avatarUrl: string | null;
};
通过侦听状态更改并调度相应的ngrx 存储操作(添加、修改、删除),将伙伴存储同步到firestore 数据库:
query$ = createEffect(() => this.actions$.pipe(
ofType(BuddiesActions.query),
switchMap(() => {
return this.uid$.pipe(
switchMap(uid => {
return this.afs.collection(`users/${uid}/buddies`).stateChanges();
})
)
}),
mergeMap(actions => {
return actions;
}),
// map the firestore actions to ngrx store actions to sync them
// TODO this adds the user reference and things fuck up here...
map((action: DocumentChangeAction<any>) => {
const data = action.payload.doc.data();
console.log({data: data});
return {
type: `[Buddies] ${action.type}`,
buddy: {
buddyStatus: data.buddyStatus,
uid: data.uid,
// this is the issue right here
// userRef: data.userRef
}
};
})
));
如果没有参考字段,则可以正确处理好友,但对好友的访问对于显示至关重要:在线状态、获取头像 url 等。
我设法同步检索某个用户的好友,但这并不是真正的方法,因为我想在用户状态等中包含更改器。
我对ngrx / angular和typescript相当陌生,这基本上是我使用这些工具/框架/概念的第一个大项目。
我检查了其他答案,但它们中的大多数都可以同步解析引用,但这并不是真正的目标,因为需要对用户信息进行观察。
解决方案
来吧,我用一种方法来解决ngrx中的此类问题。
当你对好友进行更改时,不要听好友的更改。将该侦听器作为一个单独的侦听器。然后在触发任何操作时对好友执行任何查询。无需担心立即采取行动的变化。始终从 firestore 获取数据并更新本地存储。
createEffect(() => this.actions$.pipe(
ofType(BuddiesActions.query),
switchMap(() => {
return this.uid$.pipe(
switchMap(uid => {
return this.firestoreService.buddyQuery(uid)
})
)
})
保持与查询相关的效果不变,并在那里删除不需要的好友日期获取调用,这些调用获取好友数据。
然后你需要引入一些动作,比如“监听好友更改”来监听数据库更改。
createEffect(() => this.actions$.pipe(
ofType(BuddiesActions.Listen_ON_BUDDY_CHANGES),
switchMap(() => {
// add listner to firestore and trigger that observable when any data changes happend
const data = action.payload.doc.data();
console.log({data: data});
return {
type: `[Buddies] ${action.type}`,
buddy: {
buddyStatus: data.buddyStatus,
uid: data.uid,
}
};
这应该是一个监听 firestore 中所有变化的 observable。当那里发生任何更改时,然后直接使用该数据更新本地 ngrx 存储。正如您所料,这是一个异步操作。确保在初始步骤中触发“监听好友更改”操作。
推荐阅读
- ruby-on-rails - 如何获取关联模型的最后一条记录以防止 N+1 查询?
- next.js - 如何仅允许通过下一个 js 中的语言环境子路径访问页面
- android - imageCapture.takePicture - 保存的图像转换为位图
- format - 在 fortran 中没有换行符和多次写入的格式说明符
- node.js - 我可以告诉 babel 替换输出目录吗?
- python - 更改子类的返回类型
- r - data.table:用 keyby 对 j 中的分组变量进行子集化
- docker - 如何在 Windows 命令提示符中设置环境变量,以便在 `docker run -e FOO -e ...` 中传递它们,就像使用 bash 导出一样
- python - 滑块寻找位置 pygamemixer
- complex-event-processing - 我想自动触发脚本,无需点击输入,也无需按 Enter