我从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()的值。
答案 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();
然后您有两个选择:
group$.subscribe();
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}`))
);