[英]Is there a possibility to await a subscription in angular?
I would like to show a list of posts like this: Post List我想显示这样的帖子列表:帖子列表
To show which post is favorized by a user I need data from two different collections out of my mongodb database.为了显示用户喜欢哪个帖子,我需要来自我的 mongodb 数据库中两个不同 collections 的数据。 Currently the ngOnInit of my post-list.component.ts file looks like this:
目前我的 post-list.component.ts 文件的 ngOnInit 如下所示:
ngOnInit() { this.isLoading = true; this.postsService.getPosts(this.postsPerPage, this.currentPage); this.favoritesService.getFavorites(this.postsPerPage, this.currentPage); this.userId = this.authService.getUserId(); this.postsSub = this.postsService.getPostUpdateListener().subscribe((postData: { posts: Post[]; postCount: number }) => { this.totalPosts = postData.postCount; this.posts = postData.posts; console.log("Posts fetched successful;"); }). this.favoritesSub = this.favoritesService.getFavoriteUpdateListener():subscribe( (favoriteData: { favorites; Favorite[]: postCount. number }) => { this;isLoading = false. this.favorites = favoriteData;favorites. this;fetchFavorites(). console;log("Favorites fetched successful;"). } ). this.userIsAuthenticated = this;authService.getIsAuth(). this.authStatusSub = this.authService.getAuthStatusListener();subscribe((isAuthenticated) => { this.userIsAuthenticated = isAuthenticated. this.userId = this;authService;getUserId(); }); }
Is there any possibility to first await the post data to arrive?是否有可能首先等待发布数据到达?
You have several options to achieve your wanted behavior.您有多种选择来实现您想要的行为。
Option 1:选项1:
You can use the RxJS operator switchMap
which becomes executed as soon as the subscription emits and returns a new Observable.您可以使用 RxJS 运算符
switchMap
,它会在订阅发出并返回新的 Observable 时立即执行。 See here for more infos about switchMap
;)有关
switchMap
的更多信息,请参见此处;)
I'm using your calls getPostUpdateListener
and getFavoriteUpdateListener
as example, so it would look something like this:我使用你的调用
getPostUpdateListener
和getFavoriteUpdateListener
作为例子,所以它看起来像这样:
...
this.postsSub = this.postsService
.getPostUpdateListener()
.pipe(
switchMap((postData: { posts: Post[]; postCount: number }) => {
this.totalPosts = postData.postCount;
this.posts = postData.posts;
console.log("Posts fetched successful!");
return this.favoritesService.getFavoriteUpdateListener();
})
)
.subscribe((favoriteData: { favorites: Favorite[]; postCount: number }) => {
this.isLoading = false;
this.favorites = favoriteData.favorites;
this.fetchFavorites();
console.log("Favorites fetched successful!");
});
...
Option 2:选项 2:
You can promisify your Observable with firstValueFrom
or lastValueFrom
and then you can wait for it's execution, eg with async/await.您可以使用
firstValueFrom
或lastValueFrom
承诺您的 Observable,然后您可以等待它的执行,例如使用 async/await。 See here for more information;)有关更多信息,请参见此处;)
This would look like following:这将如下所示:
async ngOnInit() {
...
const postData: { posts: Post[]; postCount: number } = await firstValueFrom(this.postsService.getPostUpdateListener());
this.totalPosts = postData.postCount;
this.posts = postData.posts;
console.log("Posts fetched successful!");
const favoriteData: { favorites: Favorite[]; postCount: number } = await firstValueFrom(this.favoritesService.getFavoriteUpdateListener());
this.isLoading = false;
this.favorites = favoriteData.favorites;
this.fetchFavorites();
console.log("Favorites fetched successful!");
...
}
Since Angular is working a lot in the reactive way I'd go with option 1;)由于 Angular 以被动方式工作很多,所以我会选择 go 和选项 1;)
For clean code you can utilize rxjs forkJoin
operator for the exact purpose.对于干净的代码,您可以使用 rxjs
forkJoin
运算符来达到确切目的。 Basically what you have is two observables getting subscribed on component initialization.基本上你所拥有的是两个在组件初始化时订阅的 observables。
forkJoin
works on joining multiple observable streams, or for the better understanding think about how Promise.all
would await all possible Promises
. forkJoin
致力于加入多个可观察的流,或者为了更好地理解考虑Promise.all
将如何等待所有可能的Promises
。
Another options to not use subscribe
and user .toPromise()
and await.另一个不使用
subscribe
和 user .toPromise()
和 await 的选项。 for reference check out this post供参考查看这篇文章
It will be better in your case to use combineLatest(RxJS v6) or combineLatestWith(RxJs v7.4).在您的情况下,使用 combineLatest(RxJS v6) 或 combineLatestWith(RxJs v7.4) 会更好。 combineLatest operator will emit every time any of the source Observables emit after they've emitted at least once.
combineLatest 运算符将在任何源 Observable 至少发出一次后发出。 As your services do not depend on each other then it will be better to use combineLatest in your case.
由于您的服务不相互依赖,因此在您的情况下使用 combineLatest 会更好。
this.postsSub = this.postsService.getPosts(this.postsPerPage, this.currentPage);
this.favoritesSub = this.favoritesService.getFavorites(this.postsPerPage, this.currentPage);
combineLatest([this.postsSub, this.favoritesSub]).pipe(
map(([postData, favoriteData]) => {
this.totalPosts = postData.postCount;
this.posts = postData.posts;
console.log("Posts fetched successful!");
this.isLoading = false;
this.favorites = favoriteData.favorites;
this.fetchFavorites();
console.log("Favorites fetched successful!");
})).subscribe();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.