如何在订阅中等待订阅?

时间:2021-03-10 17:47:47

标签: angular rxjs subscription

我需要获得包含一系列产品的订单。但是 getProduct() 比我需要的要晚,并且所有产品都未定义。我发现嵌套订阅的方式很糟糕,那么使用 mergeMap/switchMap 的正确方法是什么

getOrder(id: string) {
  this.orderService
    .getOrder(id)
    .subscribe(order => {
      order.map(item => {
        data.push(item.payload.doc.data());
        return data;
      });
      this.order = data[0].products.map(x => this.getProduct(x))
    });
}

getProduct(id: string) {
  return this.productService
    .getProduct(id)
    .subscribe(product => product);
}

 getOrderById(id: string): Observable < any > {
  return this.afs
    .collection('orders', ref => ref.where('uid', '==', id))
    .snapshotChanges();
}
 getProductById(id: string): Observable < any > {
  return this.afs
    .collection('products', ref => ref.where('uid', '==', id))
    .valueChanges();
}

1 个答案:

答案 0 :(得分:0)

我看到这里有 2 个相互独立的 observable。

  1. getOrderById() 2) getProductById()

您可以组合这两个 observable 并且只订阅一次,也可以取消订阅。像这样:


const orderByIdObservable = this.getOrderById();
const productByIdObservable = this.getProductById();

destroy$: Subject<any> = new Subject(); // This is used to destroy the subscription later

************************************************************
 *********** Using 'combineLatest' RXJS operator **********
************************************************************
// Combine the observables and destroy once done, in 1 shot.

combineLatest(orderByIdObservable,productByIdObservable)
  .pipe(
      takeUntil(this.destroy$),
      take(1)
   )
  .subscribe(
     ([orderByIdObservableData, productByIdObservableData]) => {
        if (orderByIdObservableData && productByIdObservableData) {
          // do your logic here
        }  
     }
  );

ngOnDestroy() {
   this.destroy$.next();
   this.destroy$.complete();
}



A) combineLatest - will combine all the observables and subscribe only once
B) takeUntil - this will keep subscribing until the destroy$ is completed/closed
C) take(1) - this will always take only the first value. You may or may not want to keep this
D) destroy$ - Use the Subject variable to destroy the service one the component is destroyed


************************************************************
 *********** Using 'mergeMap' RXJS operator **********
************************************************************

orderByIdObservable
  .pipe(
    mergeMap(productIdObsData => productByIdObservable.pipe(tap(data => !!data)),
    takeUntil(this.destroy$),
    take(1)
  )
  .subscribe(data => {
     console.log('Both the data merged into one', data);
     // here both the observables data are merged into one data variable
  })



A) mergeMap - if the data of the first observable is successfully subscribed, then only this mergeMap works otherwise the data after merging and subscribing is either null, undefined or some random object.
B) takeUntil - this will keep subscribing until the destroy$ is completed/closed
C) take(1) - this will always take only the first value. You may or may not want to keep this
D) destroy$ - Use the Subject variable to destroy the service one the component is destroyed

combineLatest 相对于 mergeMap 的优势在于您将只有一个订阅和一个取消订阅,而在 mergeMap 中您将有 2 个。