【问题标题】:using toPromise() and observable doesn't work async使用 toPromise() 和 observable 不能异步工作
【发布时间】:2020-10-31 08:51:31
【问题描述】:

我是使用 angular 和 firebase 的初学者,但我在学习的某个阶段遇到了困难。我的母语不是英语。

我遵循了一个使用实时数据库的教程,但我现在正在尝试使用 firestore 锻炼自己。

我有一个名为“categories”的集合,其中包含“toys”、“pizza”等类别。

我的目标是使用与我之前看到的教程类似的方法来检索这些类别,所以请不要向我发送完全不同的东西,我正在努力学习,而不是让这个工作(好吧,在某些方式但是..你明白啊)。

这就是我的服务

getCategories () {
    let categories = [];
    this.db.collection("categories").get().toPromise().then(function(querySnapshot) {
          querySnapshot.forEach(function(doc) {
            categories[doc.id] = doc.data();
          });
      console.log("getCategories() returned : ");
      console.log(categories);
      return categories;
        })
        .catch(function(error) {
          console.log("Error getting documents: ", error);
        });
  }

这是我的组件

export class ProductFormComponent {

  categories$;

  constructor(categoryService: CategoryService) {
    this.categories$ = categoryService.getCategories();
  }
}

我正在尝试使用“toPromise()”来创建一个可以获取所有类别的 Promise,并将其显示在一个名为 categories$ 的可观察对象中。

不幸的是,数据似乎在页面渲染后不久进入控制台(因为它是异步的),但可观察对象没有捕捉到变化,它永远保持未定义。

我正在使用异步“标签”,但它没有解决任何问题。

我做了很多研究,但我不明白发生了什么,所以我希望有人能在这里帮助我。

如果我找到我的答案(无论多么愚蠢),我还是会在这里发布,所以我的帖子不会无用。

谢谢大家,希望大家不要太烦收到初学者的问题。

【问题讨论】:

  • 我的猜测是你的 observable 不是有限的,因为它不是有限的,所以你没有得到任何结果。无论哪种方式,最好坚持使用Observablestake(1) 等运算符,而不是使用承诺。

标签: angular google-cloud-firestore promise observable


【解决方案1】:

您的getCategories() 方法不会返回任何内容,因此this.categories$ 将永远是undefined

如果你将它转换为一个承诺,只是希望它再次作为一个 Observable 返回,我认为你不应该首先将它转换。

更新的服务返回一个 observable

// you may want to type your observable better...
getCategories (): Observable<any[]> {
    return this.db.collection("categories").get().pipe(
        map(querySnapshot => {
          let categories = []; //I don't think you actually want an array here, but thats what your existing code had
          querySnapshot.forEach(function(doc) {
            // you were originally  trying to set the index of an array to be the doc ID, this is probably going to cause an issue
            // categories[doc.id] = doc.data();
            // this will add the data to the array, you probably lose the ID though
            categories.push(doc.data());
          });
          console.log("getCategories() returned : ");
          console.log(categories);
          return categories;
         
        }),
        catchError(error => { 
           console.log("Error getting documents: ", error);
           return []; // You need to determine what to do here, return an empty array, or possibly re-throw the error with throwError(error)
        });

    );

更新的组件。请注意,我们仍然没有订阅,所以它仍然不会做任何事情。您应该通过async 管道在某处订阅模板。

export class ProductFormComponent {

  categories$: Observable<any[]>; // type this better...

  constructor(categoryService: CategoryService) {
    this.categories$ = categoryService.getCategories();
  }
}

带有异步管道的示例模板

<ul>
<li *ngFor="let category of categories$ | async">
{{category | json}} <!-- do something better here to show your data -->
</li>
</ul>

【讨论】:

  • 感谢您的回答,我明白当您谈论“不返回任何内容”时我的错误是什么。谢谢!出于安全考虑,建议使用“Observable”更好的理解或者这是我无法避免的事情?我做了更改,我不工作,它仍然从firestore检索数据,但我不能让它们出现在页面上,即使使用示例模板.似乎getCategories()被调用了两次。我有两次控制台消息“getCategories()返回...数组”。也许我在更改时出错了..谢谢。
  • 没有看到完整的工作代码,我不知道为什么它被调用了两次。如果您使用将在模板中订阅的 aysnc 管道,但您也可能在组件中的某处调用 .subscribe() 。最好键入方法的返回值,这样如果代码中有错误,编译器会抱怨,但实际上并没有返回。
猜你喜欢
  • 1970-01-01
  • 2019-03-06
  • 2017-12-28
  • 2016-11-28
  • 1970-01-01
  • 2021-04-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多