angular - 从 Observable 发出,然后进行额外的 REST API 调用以获取更多详细信息

我有两种方法可以对 Rest API 进行 HTTP 调用。一个是 getProducts(),它将返回一个产品数组,另一个是 getProductsDetail(),它可以将该数组作为参数,并返回填充了附加字段的产品数组。

我想依次调用这两个 API,getProductsDetail() 取决于 getProducts() 的结果,但我希望我的 Observable 一旦准备好就从 getProducts() 发出结果。然后让 getProductsDetail() 在此调用返回时发出额外的详细信息。

有没有办法使用像 concatMap 或 mergeMap 这样的 RxJS 运算符来做到这一点?我想让我的模板尽快开始显示,但在可用时填写额外数据

更新:

您好,感谢您的回复!对不起,我目前只有伪代码,但我认为我最初的尝试将类似于 Authur 下面的内容

initProductsPage(): Observable<Products[]>{
this.productsService.getProducts().pipe(
  switchMap(
    (products: Products[]) => {
      // would like to also emit products here

      return this.productsService.getProductsDetail(products);
    }
  )

}

我的理解是,在这种情况下,initProductsPage() 的订阅者只会在 getProductsDetail() 返回时收到输出。我想让该订阅者在执行 getProductsDetails() 时获得产品。

回答1

假设 getProducts()getProductsDetail() 返回一个 Observable<Product[]>,你可以这样做:

getProductsWithDetailsHydration(): Observable<Product[]> {
  const productsShared$ = this.getProducts().pipe(share()); // <- to share same GET products request.

  return merge(
    productsShared$, // <- 1st obs Gets and emits Products
    productsShared$.pipe( //<- 2nd obs Gets details using products response and emit Products with Details
      concatMap((products) => this.getProductsDetail(products))
    )
  );
}

干杯

回答2

另一种来自 API 端的方法是使用 getProductDetail$() 方法。其中可以获取单个产品的详细信息。然后您可以轻松地在模板本身中使用 async 并填充模板。

示例模板代码

<ng-container *ngIf="getProduct$() | async as product">
    // Some info on product
    <div>{{product.title}}</div>
    <ng-container *ngIf="getProductDetail$(product.id) | async as productDetail">
         // Some info on product details
        <div>{{productDetail.description}}</div>
    </ng-container>
</ng-container>

回答3

我认为解决这个问题的更好方法是将两个可观察对象分开。

然后您可以订阅并获得 values:

// Class variables
  products: Products[];
  products$: Observable<Products[]>;
  productsDetails: ProductsDetails[];
  productsDetails$: Observable<ProductsDetails[]>;

  // Call OnInit or OnChanges depending of your needs
  initProductsPage(): void {
    // Initialize the observables
    this.products$ = this.productsService.getProducts();
    this.productsDetails$ = this.products$.pipe(
      switchMap((products) => this.getProductsDetail(products))
    );

    // Using take(1) to complete the observable after it gets the value
    this.products$.pipe(take(1)).subscribe(products => {
      this.products = products;
    });

    // Using take(1) to complete the observable after it gets the value
    this.productsDetails$.pipe(take(1)).subscribe(productsDetails => {
      this.productsDetails = productsDetails;
    });
  }

然后你可以在你的模板中使用 productsproductsDetails

您也可以使用 |async 直接在模板上使用 observables,在这种情况下 initProductsPage() 的第二部分将不是必需的。

// Class variables
  products: Products[];
  products$: Observable<Products[]>;
  productsDetails: ProductsDetails[];
  productsDetails$: Observable<ProductsDetails[]>;

  // Call OnInit or OnChanges depending of your needs
  initProductsPage(): void {
    // Initialize the observables
    this.products$ = this.productsService.getProducts();
    this.productsDetails$ = this.products$.pipe(
      switchMap((products) => this.getProductsDetail(products))
    );
  }

相似文章

最新文章