无法访问变量数据,也无法在Angular Firestore中返回它

时间:2019-03-22 01:18:31

标签: angular firebase google-cloud-firestore angular7

我从firestore中访问文档的代码如下。

let data;
this.firestore.collection('groups').doc(tempId).ref.get().then(function(doc) {
  if (doc.exists) {
      data = doc.data();
      console.log("Document data:", doc.data());   // Gives correct data here
  } else {
      console.log("No such document!");
  }
}).catch(function(error) {
    console.log("Error getting document:", error);
});
console.log("Service Data :: " + data); //It says undefined here.

在这里,我想将 doc.data()的数据返回到另一个组件。但是,在 console.log(“ Service Data ::” + data); 中,它表示未定义。

所以,我很困惑,为什么数据变量中没有 doc.data()的值。

2 个答案:

答案 0 :(得分:1)

这是因为第二个控制台第一个控制台之前执行,该线程将向您的 firestore 发送请求,然后它不会等待响应,也不会执行其他代码行。因此,您的第二个控制台在第一个控制台之前执行。

let data;
this.firestore.collection('groups').doc(tempId).ref.get().then(function(doc) {
  if (doc.exists) {
      data = doc.data();
      console.log("Document data:", doc.data());   // first console
  } else {
      console.log("No such document!");
  }
}).catch(function(error) {
    console.log("Error getting document:", error);
});
console.log("Service Data :: " + data); //second console

如果要更改此行为,请在第一个控制台旁边调用第二个控制台。

  

如果要将数据传递给其他组件,请使用BehaviourSubject

  public  dataSource = new BehaviorSubject<any>([]);

  this.dataSource.next(doc.data()); 
  console.log("Document data:", doc.data());   // first console

在服务类的帮助下将此dataSource对象传递给您的其他组件,并作为常规Observable进行订阅。点击此链接以获取有关angular-behaviorsubject-service

的更多信息

第二个Component.ts

constructor(private service: Commonservice) { }

someMethod() {
  this.service.dataSource.subscribe((response: any) =>{
    // do something with data
  })
}

答案 1 :(得分:1)

.get()方法返回一个诺言,一旦您调用.then(),该诺言就会异步执行。因此,要执行的下一行是 console.log("Service Data :: " + data);。 Javascript不等待承诺被解决,而是继续执行下一个同步行即第二个控制台。

我通常的处理方式是将整个承诺传递给其他组件或更佳的组件,我使用.valueChanges()中的.doc()返回一个可观察值,并在我要传递给的组件:

// Get Observable on document. Returns Observable<any>
const group$ = this.firestore.doc('/groups' + tempId).valueChanges();

然后您有两个选择:

  1. 使用group$.subscribe();
  2. group$传递到所需的组件,然后在其中使用异步管道

第一个选项:

// In your component:
let data;
group$.subscribe(doc => {
  if (doc.exists) {
    data = doc
    console.log("Document data:", doc);   // No need to call data().
  } else {
    console.log("No such document!");
  },
  error => console.log("Error getting document:", error);
)

第二个选项,传递到您希望评估可观察对象并显示数据的组件中:

<div *ngIf="group$ | async as doc">
  Your html here {{ doc.someProperty }} further html here...
</div>

我个人更喜欢第二种选择,因为它与框架很好地结合在一起,并且可以避免产生异步错误。

查看docs here的angularfire2的Github存储库。如果不需要手工评估可观察的代码,则我不会这样做,而是由框架来处理。

最后一件事:如果您使用observable并想在使用异步管道时进行一些错误处理,那么您可能希望在创建observable时这样做:

// Get Observable on document. Returns Observable<any>
// In error case, returns Observable of the error string
const group$ = this.firestore.doc('/groups' + tempId).valueChanges()
  .pipe(
    catchError(error => of(`Error getting document: ${error}`))
  );