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

问题描述 投票:0回答:2

我从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()的值。

angular firebase google-cloud-firestore angular7
2个回答
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
投票

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

我通常采用的方法是将整个承诺传递给另一个组件或者更好,我使用.valueChanges().doc()返回一个observable,并在我传递给的组件中使用异步管道:

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

然后你有两个选择:

  1. 使用group$.subscribe();
  2. group$to传递给您想要的组件并在那里使用异步管道

第一种选择:

// 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);
)

第二个选项,传入您希望评估observable的组件以及显示的数据:

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

就个人而言,我更喜欢第二种选择,因为它很好地配合了框架,使我不会犯异步错误。

看看angularfire2的Github repo for docs here。如果不需要在代码中手动评估observable,我不会这样做,让框架处理它。

最后一件事:如果您使用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}`))
  );
© www.soinside.com 2019 - 2024. All rights reserved.