在运行其他函数之前等待异步值

时间:2018-03-07 20:28:11

标签: angular typescript google-cloud-firestore

我正在尝试初始化组件中的两个不同的值,这两个值都是从firestore异步检索的,但是我用来获取第二个的快照方法需要第一个的值。

因为这些是异步的,所以获取第二个的方法在实际检索它所依赖的值之前运行,因此导致以下错误,因为this.invoice试图在请求之前初始化。 userId已完成:

"Property 'items' does not exist on type 'Observable<Invoice>'"...

组件:

import { Component, OnInit, AfterViewInit, ViewChild, 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'
  ]

  @ViewChild(MatPaginator) paginator: MatPaginator;
  @ViewChild(MatSort) sort: MatSort;

  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.invoice.subscribe(invoice => {
            this.itemsData.data = invoice.items;
        })
    })

  }

  ngOnInit() {

  }

  ngAfterViewInit() {
    this.itemsData.paginator = this.paginator;
    this.itemsData.sort = this.sort;
  }

}

2 个答案:

答案 0 :(得分:0)

为什么不试试这个

this.db.collection('/users').doc(this.userId).collection('/invoices').doc(this.invoiceId).ref.get().then(snapshot => {
        this.invoice = snapshot.data() as Observable<Invoice>.subscribe(invoice => {
            this.itemsData.data = invoice.items;
        })
    })

答案 1 :(得分:0)

要根据路由器可观察的结果创建firebase observable,您可以使用flatMap familly(mergeMapswitchMapconcatMap等的运算符。)

在你的情况下,我认为switchMap将是最好的选择,它需要一个可观察的,当它发出时,它会根据发出的值创建一个新的observable。

this.route.params
    .switchMap(params => {
        // Async fetch on firebase, based on the route param
        const invoiceId = params.id;
        return Observable.fromPromise(
            this.db.collection('/users')
                .doc(this.userId)
                .collection('/invoices')
                .doc(invoiceId)
                .ref.get()
        );
    }).switchMap(snapshot => {
        // Async observable of the snapshot.
        return snapshot.data() as Observable<Invoice>;
    }).subscribe(invoice => {
        this.itemsData.data = invoice.items;
    })

我根据您的类型提示编写了代码,如果您搞乱了类型,它就不会工作,但逻辑就在这里。