Angular 角度及;Firestore:异步获取firebase数据

Angular 角度及;Firestore:异步获取firebase数据,angular,firebase,asynchronous,google-cloud-firestore,Angular,Firebase,Asynchronous,Google Cloud Firestore,如果标题有点错误,我很抱歉,但是我在这里发布这个问题的原因是因为我有点茫然,在网上找不到我想要的东西。我也不知道我到底在找什么 所以我有一个angular应用程序,我使用Firestore作为数据库。因此,我使用这段代码在服务中获取我的收藏: this.userAsteroid$ = this.afs.collection<UserAsteroid>(this.collection).valueChanges(); 因此,基本上,我的组件是特定小行星的详细信息页面,当我的收藏有一个

如果标题有点错误,我很抱歉,但是我在这里发布这个问题的原因是因为我有点茫然,在网上找不到我想要的东西。我也不知道我到底在找什么

所以我有一个angular应用程序,我使用Firestore作为数据库。因此,我使用这段代码在服务中获取我的收藏:

this.userAsteroid$ = this.afs.collection<UserAsteroid>(this.collection).valueChanges();
因此,基本上,我的组件是特定小行星的详细信息页面,当我的收藏有一个文档,其中包含小行星id和登录用户的id时,我希望我的bool hasAsteroid设置为true

这是组件的html:

    <div [hidden]="loading">
  <div class="columns" *ngIf="!hasAsteroid && user">
    <div class="column">
        <button class="button is-primary is-outlined" type="button" (click)="addAsteroid(id)">Add to my asteroids</button>
    </div>
  </div>
如您所见,我正在将用户保存的所有小行星ID推送到一个数组中,以便稍后使用它们进行api调用

我没有费心在这里编写其余的代码,因为我知道它不会工作,因为函数不是异步的

如果有人有一个解决方案,或者可以为我指出正确的文档,我将不胜感激

编辑:

在课堂上进一步研究之后,我解决了部分问题,并且能够更准确地确定问题所在,但问题仍然存在。在我最初展示的两个函数中,我都有一部分使用了这个代码块

this.authService.userData$.subscribe(data => {
  this.user = data;

  this.userAsteroid$ = this.userAsteroidService.getAsteroids();

  this.userAsteroid$.subscribe(asteroids => {
    asteroids.forEach(document => {
      if (document.asteroidId == this.id && document.userId == this.user.uid) {
        this.hasAsteroid = true;
        console.log("test: ", this.hasAsteroid);
      }
      console.log(document);
    });
  });
});
基本上我订阅我的authSerivce来确定我的用户,在订阅中我订阅了我的firestore服务,然后我做了一些事情

当我最初加载我的组件时,这一切都起作用。但是,我在路由中使用参数来对“选项卡”进行排序。我在ngOnit中订阅这些参数,这样当我单击导航中的链接时,我的页面将使用正确的参数更新组件。在这个订阅中,我回忆起我的功能

然而,当我回忆起这个函数时,它仍然会订阅用户,它仍然会从firestore获得可观察的,但是它不会再订阅可观察的。基本上,当我回忆起函数时,从这一行到下一行的所有内容都不起作用:

this.userAsteroid$.subscribe(asteroids => {

有人知道为什么吗?

将文档查找移到auth订阅中如何

getUserFeed() {
  this.authService.userData$.subscribe(data => {
    this.user = data
    this.userAsteroid$.subscribe(asteroids => {
      asteroids.forEach(document => {
        if (document.userId == this.user.uid) {
          console.log(document.asteroidId);
          this.dataArray.push(document.asteroidId);
        }
      });
    })}
  });
  this.userAsteroid$ = this.userAsteroidService.getAsteroids();
}
通过这种方式,您可以保证只有在
This.user
可用后才能设置
userAsteroid$
订阅


如果您使用此方法,您可能希望检测是否已订阅此.userAsteriud$,并在这种情况下跳过重新订阅。

将文档查找移动到身份验证订阅中如何

getUserFeed() {
  this.authService.userData$.subscribe(data => {
    this.user = data
    this.userAsteroid$.subscribe(asteroids => {
      asteroids.forEach(document => {
        if (document.userId == this.user.uid) {
          console.log(document.asteroidId);
          this.dataArray.push(document.asteroidId);
        }
      });
    })}
  });
  this.userAsteroid$ = this.userAsteroidService.getAsteroids();
}
通过这种方式,您可以保证只有在
This.user
可用后才能设置
userAsteroid$
订阅


如果你走这条路线,你可能会想检测你是否已经订阅了
this.userAsteriud$
,在这种情况下跳过重新订阅。

你需要在获得用户id后才在小行星上启动请求。因此你的代码应该在用户数据的订阅结果中

否则,它取决于您接收响应的顺序:如果您在
之前获得小行星,则该用户尚未设置

您可以在每个事件处理程序中通过
console.log
看到这一点,这应该是显而易见的

因此,您的代码将变成:

getUserFeed(){
this.authService.userData$.subscribe(数据=>{
这个用户=数据;
this.userAsteroid$=this.userAsteroidService.getAsteroids();
this.userAsteroid$.subscribe(asteroids=>{
asteroids.forEach(文档=>{
if(document.userId==this.user.uid){
console.log(document.id);
this.dataArray.push(document.id);
}
});
});});
}

只有在获得用户id后,您才需要启动小行星上的请求。因此,您的代码应该在用户数据的订阅结果中

否则,它取决于您接收响应的顺序:如果您在
之前获得小行星,则该用户尚未设置

您可以在每个事件处理程序中通过
console.log
看到这一点,这应该是显而易见的

因此,您的代码将变成:

getUserFeed(){
this.authService.userData$.subscribe(数据=>{
这个用户=数据;
this.userAsteroid$=this.userAsteroidService.getAsteroids();
this.userAsteroid$.subscribe(asteroids=>{
asteroids.forEach(文档=>{
if(document.userId==this.user.uid){
console.log(document.id);
this.dataArray.push(document.id);
}
});
});});
}

据我所知,您的设置应该可以正常工作。请显示相应的组件html代码。我已将其添加到问题中。据我所知,您的设置应该可以正常工作。请显示相应的组件html代码。我将其添加到问题中。这似乎有效。但是,现在,当我重新加载页面时,它会将每个小行星显示两次。这是因为我已经订阅了吗?另外,我现在不知道如何跳过重新订阅,你能给我指一些文档吗?我对订阅不是很有经验,…订阅无法在页面重新加载后继续,所以不应该是这样。老实说,我也不是这些特定订阅的专家,但AngularFire文档应该包含您所需要的所有内容:这似乎很有效。但是,现在,当我重新加载页面时,它会将每个小行星显示两次。这是因为我已经订阅了吗?另外,我现在不知道如何跳过重新订阅,你能给我指一些文档吗?我对订阅不是很有经验,…订阅无法在页面重新加载后继续,所以不应该是这样。老实说,我也不是这些特定订阅的专家,但AngularFire文档应该包含您所需的所有内容:嘿,伙计,谢谢您的回答!我仍然有一个问题,我编辑了我的初始问题(在底部的“编辑”下)。你能看一看吗
getUserFeed() {
  this.authService.userData$.subscribe(data => {
    this.user = data
    this.userAsteroid$.subscribe(asteroids => {
      asteroids.forEach(document => {
        if (document.userId == this.user.uid) {
          console.log(document.asteroidId);
          this.dataArray.push(document.asteroidId);
        }
      });
    })}
  });
  this.userAsteroid$ = this.userAsteroidService.getAsteroids();
}