0

我很难将来自firebase的云存储与Angular一起使用,以至于我最终陷入了死胡同。

我正在尝试做一些简单的事情:从数据库中检索数据并将其保存在类变量中以供进一步处理。

races: Race[]
ngOnInit() {
    this.races = []

    this.userResolver.getUserInfo().then(
      res => {
        this.userInfo = res
        let docRef = this.db.collection('/players/').doc(this.userInfo.uid).ref
        docRef.get().then(function(doc) {
          if (doc.exists) {
              console.log("Document data:", doc.data());
              let res = doc.data().races
              console.log("res:", res);
              res.forEach(item=>{
                console.log("item:", item);
                console.log(item.id);
                let race = new Race(item.id, item.title, item.progress, item.thumbnail)
                console.log(race);
                this.races.push(race)
              })
              console.log(this.races);

          } else {
              console.log("No such document!");
          }
      }).catch(function(error) {
          console.log("Error getting document:", error);
      });
    }

这是控制台日志:

Document data: {races: Array(2)}
res: (2) [{…}, {…}]
item: {id: "Whu855ZbOsIM9SoIE6pu", progress: 50, thumbnail: "", title: "Brasil"}
(id) Whu855ZbOsIM9SoIE6pu
Race {id: "Whu855ZbOsIM9SoIE6pu", progress: 50, thumbnail: "", title: "Brasil"}
Error getting document: TypeError: Cannot read property 'races' of undefined
at menu.component.ts:39
at Array.forEach (<anonymous>)
at menu.component.ts:34
at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke (zone.js:388)
at Object.onInvoke (core.js:3820)
at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke (zone.js:387)
at Zone.push../node_modules/zone.js/dist/zone.js.Zone.run (zone.js:138)
at zone.js:872
at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:421)
at Object.onInvokeTask (core.js:3811)

实际上,我试图将类的成员更改为在函数中声明的变量(例如让比赛)并且它有效,但是在我将它分配给类成员的那一刻它没有。它看起来像在承诺中,它不知道“this”,因为我创建了另一个类变量,当我尝试打印它时,我得到了同样的错误。

如果数据直接来自使用以下代码的集合,我已经设法从 Firebase 检索数据:

this.db.collection('/cards')
    .valueChanges()
    .subscribe(res => {
        this.cards = res.map(card=> card as Card);

但是,当我想过滤请求并在所有玩家中只选择一个玩家时,我无法让它工作。我确实得到了数据,但我无法保存或将其投射到我的界面。

我将不胜感激任何帮助。我已经尝试了我所看到的一切,但实际上 Firebase for Angular 的文档非常糟糕。

请阅读我的问题并避免使用诸如 collection('players') 之类的内容发表评论,仅此而已。我需要选择集合中的播放器。

谢谢

-- 修复(感谢 Renaud Tarnec):

let docRef = this.db.collection('/players/').doc(this.userInfo.uid).ref;
docRef.get().then(doc => {
            if (doc.exists) {
                let res = doc.data().races
                res.forEach(item=>{
                  this.races.push(item as Race)
                })
            } else {
                console.log("No such document!");
            }
        }).catch(function(error) {
            console.log("Error getting document:", error);
        });

此外,我将我的类 Race 更改为接口以避免调用构造函数。

4

1 回答 1

3

我根本不是角度专家,但我认为您在this作为处理程序传递给docRef.get().then().

通过使用箭头语法,您应该解决它。执行以下操作:

...
docRef.get().then(doc => {
          if (doc.exists) {
              console.log("Document data:", doc.data());
              let res = doc.data().races
              console.log("res:", res);
              res.forEach(item=>{
                console.log("item:", item);
                console.log(item.id);
                let race = new Race(item.id, item.title, item.progress, item.thumbnail)
                console.log(race);
                this.races.push(race)
              })
              console.log(this.races);

          } 
...

有关更多详细信息,请参阅此 SO 问题和答案:箭头函数与函数声明/表达式:它们是否等效/可交换?

您也可以按如下方式解决:

races: Race[]
ngOnInit() {
    const self = this;
    self.races = []

    self.userResolver.getUserInfo().then(
      res => {
        self.userInfo = res;
        let docRef = self.db.collection('/players/').doc(self.userInfo.uid).ref
        docRef.get().then(function(doc) {
          if (doc.exists) {
              console.log("Document data:", doc.data());
              let res = doc.data().races
              console.log("res:", res);
              res.forEach(item=>{
                console.log("item:", item);
                console.log(item.id);
                let race = new Race(item.id, item.title, item.progress, item.thumbnail)
                console.log(race);
                self.races.push(race)
              })
              console.log(self.races);

          } else {
              console.log("No such document!");
          }
      }).catch(function(error) {
          console.log("Error getting document:", error);
      });
    }

在这种情况下,“即使在上下文发生变化的情况下,self也使用它来维护对原始文件的引用”,请参阅此 JavaScript 惯用语的基础:var self = this?this

于 2018-10-22T08:54:36.260 回答