我有此代码:
this.categoriesSub = this.categoriesService.getCategories().subscribe(
categories => {
// This line is reached on the second run
this.postsSub = this.postsService.getPosts().subscribe(
posts => {
// This line is NOT reached on the second run
posts.forEach(p => p.category = categories.find(c => c.id === p.categoryId));
this.posts = posts;
}
);
}
);
在这里,我收到了一堆帖子,并且对于每篇帖子,我也都填充了category
字段。
第一次加载该组件时效果很好,但是如果我导航到另一条路线,然后在浏览器中单击“后退”按钮以返回到该组件,它将不再获取帖子。
是否有更好的方法来链接.subscribe()
通话?我已经看到了使用switchMap
的示例,但是我不知道如何在这里实现。我已经尝试过像这样使用forkJoin
:
forkJoin(
this.categoriesService.getCategories(),
this.postsService.getPosts()
).subscribe(([categories, posts]) => console.log(categories));
...只是看我是否获得了数据,但它不起作用。
编辑:更准确地说:问题是在第二次运行时,未执行第二个.subscribe()
调用的回调。没有错误,没有任何错误。看起来好像被跳过了。我在未执行的行上添加了注释。
稍后编辑:这是帖子服务:
export class PostsService {
postsCollection: AngularFirestoreCollection<Post>;
posts: Observable<Post[]>;
constructor(private firestore: AngularFirestore) {
this.postsCollection = this.firestore.collection('posts');
this.posts = this.postsCollection.snapshotChanges().pipe(
map(actions => actions.map(a => {
const data = a.payload.doc.data() as Post;
const id = a.payload.doc.id;
return { id, ...data };
}))
);
}
getPosts(): Observable<Post[]> {
return this.posts;
}
getPost(id: string): Observable<Post> {
return this.posts.pipe(
map(posts => posts.find(p => p.id === id))
);
}
}
在这里我在模板中使用this.posts
:
<app-post-item *ngFor="let post of posts" [post]="post"></app-post-item>
帖子内容:
<div class="post-item" @fade>
<span class="badge post-category">{{ post.category.name }}</span>
<a [routerLink]="['./', post.id]" class="post-title text-strong">{{ post.title }}</a>
<span class="post-date text-medium">{{ post.date.seconds * 1000 | date }}</span><br>
<img *ngIf="post.coverUrl" class="post-cover-img" src="{{ post.coverUrl }}" alt="none">
<p class="post-body">{{ postBody }}</p>
<div class="actions">
<a [routerLink]="['./', post.id]" class="read-more-button strong">Read More!</a>
</div>
</div>
答案 0 :(得分:2)
forkJoin仅在完成所有可观察项时发射。尝试改用zip。但是您需要确保两个可观察对象都发出值或错误。如果getCategories
和getPosts
是网络请求,则zip
优于switchMap
,因为这些请求将并行执行。
zip(
this.categoriesService.getCategories(),
this.postsService.getPosts()
).subscribe(([categories, posts]) => {
posts.forEach(p => p.category = categories.find(c => c.id === p.categoryId));
});
问题的根源是您的服务共享了are hot by design的AngularFire可观察对象。 getPosts()
和getCategories()
方法应该创建新的可观察对象,例如:
export class PostsService {
postsCollection: AngularFirestoreCollection<Post>;
constructor(private firestore: AngularFirestore) {
this.postsCollection = this.firestore.collection('posts');
}
getPosts(): Observable<Post[]> {
return this.postsCollection.snapshotChanges().pipe(
map(actions => actions.map(a => {
const data = a.payload.doc.data() as Post;
const id = a.payload.doc.id;
return { id, ...data };
}))
);
}
}
此外,您不应直接使用Subscribe / Unsubscribe Observable方法。忘记退订很容易。改用async管道,该管道在组件销毁时会自动取消订阅。
@Component({
template: `<app-post-item *ngFor="let post of posts$ | async [post]="post"></app-post-item>`,
})
class MyComponent {
readonly posts$: Observable<Post[]>;
constructor(
postsService: PostsService,
categoriesService: CategoriesService
) {
this.posts$ = zip(
categoriesService.getCategories(),
postsService.getPosts()
).pipe(
map(([categories, posts]) => {
posts.forEach(p => p.category = categories.find(c => c.id === p.categoryId));
return posts;
}));
}
}
答案 1 :(得分:0)
问题是我再次订阅了另一个组件中的{
dependencies: {
expo: "^34.0.1",
react: "16.8.3",
"react-dom": "^16.8.6",
"react-native": "https://github.com/expo/react-native/archive/sdk-34.0.0.tar.gz",
"react-native-gesture-handler": "^1.3.0",
"react-native-web": "^0.11.4",
"react-navigation": "^3.11.1"
},
devDependencies: {
"@types/react": "^16.8.23",
"@types/react-native": "^0.57.65",
"babel-preset-expo": "^6.0.0",
typescript: "^3.4.5"
}
}
,但是没有在Select
p.Id, max(p.author) author, max(p.community) community, max(p.created) created
,max(p.title) title , max(p.content) content
,GROUP_CONCAT(DISTINCT (cttc.category)) category
, GROUP_CONCAT(DISTINCT (ctatc.name)) Tag
From
Post p
inner Join Communnity c On c.Id = p.CommId
right Join (
Select cc.Community, tc.category, tc.Id
From
TagCategory tc
inner join CommunnityTagCategories cc
ON cc.Category = tc.Id) cttc
ON p.Commid = cttc.Community
Left join (
Select
p.post,t.name,ct.category
From
PostTags p
inner join Tag t ON t.Id = p.Tag
inner join TagCategorised ct ON ct.Tag = t.Id
) ctatc
ON ctatc.category = cttc.id and ctatc.post = p.id
GROUP BY p.Id;
方法中调用postsService
。
这就是为什么只有该呼叫无法正常工作的原因。