【问题标题】:Angular Lifecycle Hook - Async data undefined OnInitAngular Lifecycle Hook - 异步数据未定义 OnInit
【发布时间】:2018-08-15 16:31:35
【问题描述】:

我正在尝试访问从 firestore 文档加载的对象中的数组,但无法在 ngOnInit 中对其进行操作,因为几秒钟后它在 DOM 中呈现之前,它是未定义的。

因此,我无法设置填充了我需要访问的数组中的数据的新材质 MatTableDatasource,并且在尝试这样做时,CLI 会返回

Observable 类型上不存在属性“项目”

view=invoice.component.ts:

import { Component, OnInit, AfterViewInit, Input } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { MatPaginator, MatTableDataSource, MatSort } from '@angular/material';
import { Observable } from 'rxjs/Observable';

import { AngularFireDatabase } from 'angularfire2/database';
import { AngularFirestore, AngularFirestoreCollection, AngularFirestoreDocument } from 'angularfire2/firestore';

import { AuthService } from '../../services/auth.service';
import { InvoiceService } from '../invoice.service';

import { Invoice } from '../invoiceModel';

@Component({
  selector: 'app-view-invoice',
  templateUrl: './view-invoice.component.html',
  styleUrls: ['./view-invoice.component.scss']
})

export class ViewInvoiceComponent implements OnInit, AfterViewInit {

  userId: string;
  invoiceId: string;
  invoice: Observable<Invoice>;
  items: object[];

  itemsData = new MatTableDataSource();

  tableColumns = [
    'description'
  ]

  constructor(private authService: AuthService, private invoiceService: InvoiceService, private db: AngularFirestore, private route: ActivatedRoute) {
    this.userId = this.authService.user.uid;

    this.route.params.subscribe(params => {
        this.invoiceId = params.id;
    })

    this.db.collection('/users').doc(this.userId).collection('/invoices').doc(this.invoiceId).ref.get().then(snapshot => {
        this.invoice = snapshot.data() as Observable<Invoice>;
        this.itemsData = this.invoice.items; <-- Here. "Property items does not exist on 'Observable<Invoice' "...
    })

  }

  ngOnInit() {

  }

  ngAfterViewInit() {

  }

}

【问题讨论】:

    标签: angular rxjs google-cloud-firestore lifecycle


    【解决方案1】:

    回答新版本

    由于您有几个需要在链中调用的可观察对象:

    • 您的 API 调用取决于可观察参数的结果,
    • 设置数据字段取决于 API 调用的结果
    • 之间似乎有一些可观察的

    所以你应该使用flatMaps 来帮助你链接可观察的调用。

    this.route.params
        .map(params => params.id)
        .do(id => { 
            // you can remove this block completely if you don't have other use of this.invoiceId
            this.invoiceId = id; 
        }) 
        .flatMap(invoiceId => Observable.fromPromise(
            this.db.collection('/users').doc(this.userId).collection('/invoices').doc(invoiceId).ref.get())))
        .flatMap(snapshot$ => snapshot$) // not completely sure if needed, try with or without this line
        .flatMap(snapshot => snapshot.data() as Observable<Invoice>)
        .subscribe(
            invoice => { 
                this.itemsData.data = invoice.items; 
                console.log('Loaded items : ');
                console.log(invoice.items);
            }, 
            err => {
                console.log('There was an error :');
                console.log(err);
            }
         ); 
    

    【讨论】:

    • 谢谢,只需要在subscribe方法中从this.itemsData改成this.itemsData.data
    • @nick.cook 哦,是的,也许,我刚刚从您的问题中的分配中调整了异步 Observable 部分。很高兴它有帮助!
    • 我刚刚注意到,它在控制台中说 this.invoice.subscribe 不是一个函数。我尝试将订阅从构造函数的文档快照移动到 afterViewInit 方法,但随后它返回“无法读取未定义的属性订阅”
    • 您必须检查 this.invoice 是否未定义。你可以这样做:if (this.invoice) { this.invoice.subscribe.... }。话虽如此,这意味着snapshot.data() as Observable&lt;Invoice&gt; 返回未定义。 snapshot.data() 究竟返回了什么?你有一些文档的链接吗?
    • @nick.cook 哦,我注意到了可能的原因。你还有另一个异步问题。您在 this.invoiceId 未定义时使用它(它在之前编写的另一个异步调用中设置,但尚未执行)。所以它不能按原样工作。您必须等待 invoiceId 设置。给我一些时间,我会写出解决方案,或者也许其他人会这样做。
    猜你喜欢
    • 2020-05-30
    • 1970-01-01
    • 1970-01-01
    • 2016-09-12
    • 2020-08-23
    • 2020-05-30
    • 2016-03-27
    • 1970-01-01
    • 2020-06-18
    相关资源
    最近更新 更多