【问题标题】:Can't access a variable data and cannot return it in Angular Firestore无法访问变量数据,也无法在 Angular Firestore 中返回它
【发布时间】:2019-03-22 01:18:31
【问题描述】:

我从 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); 中显示未定义。

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

【问题讨论】:

  • 好的。对不起。收回我的回答。我今天无法测试我的代码,很抱歉。将返回经过测试的解决方案,但如果可以的话,它将依赖 valueChanges() 和 observables 而不是 Promises。
  • 就代码工作而言,我很好

标签: angular firebase google-cloud-firestore angular7


【解决方案1】:

这可能是 second console 语句在 first 之前执行的原因。基于线程的执行将向您的 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 对象传递给您的其他组件。点击此链接了解更多关于angular-behaviorsubject-service的信息

第二个 Component.ts

constructor(private service: Commonservice) { }

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

【讨论】:

  • 哦,我明白了。但是如果我想将数据传递给另一个组件该怎么办?
  • 嗨,我很抱歉,但我是新手,所以请你帮我写代码,我该如何实现?我试图理解该链接,但无法将其与我的要求进行比较。
  • @Virus 我已经更新了我的答案,检查一次。我希望这能解决您的问题。
  • 我试过了,但得到了类似“获取文档时出错:TypeError:无法读取未定义的属性‘dataSource’”的错误。此外,当我订阅时,我如何获取那里的数据意味着哪个变量?
【解决方案2】:

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

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

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

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

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

就我个人而言,我更喜欢第二种选择,因为它与框架很好地配合,并且可以防止我犯异步错误。

查看 angularfire2 的 Github 存储库以获取文档 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}`))
  );

【讨论】:

  • 好的,所以我根据您的 cmets 进行了尝试,它在控制台中给了我一个错误,例如“无法读取未定义的属性 'subscribe'”
  • 或者如何在另一个组件中使用异步管道?
  • 实际上您提供的代码在一个方法中 get(id: string) 那么我应该在这个方法中返回什么?以及如何在另一个组件中使用这个方法来获取数据。
  • 抱歉,必须更新我的代码。往上看。对于传递,您在其他组件中定义 @Input() 变量并在模板中使用可观察对象(例如 ...content
  • 在更新的代码中,它给出了类似“属性'then'不存在于类型'Observable”的错误
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-09-22
  • 1970-01-01
  • 1970-01-01
  • 2021-08-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多