首页 > 解决方案 > Angular 2+,在 forEach 循环中具有嵌套订阅的订阅对象数组

问题描述

我有两个不同的 Observable。一,获取项目列表。它返回一个对象数组,其中 json 键之一是“fakturaId”:

getInvoiceForResidence() {
    return this.httpClient.get<Invoices>(
      this.url
    );
  }

我可以使用这个“fakturaId”来放入第二个 Observables 并获取特定对象的详细信息:

getInvoicePreview(fakturaId: number) {
    return this.httpClient.get<InvoicePrev>(this.url + fakturaId);
  }

要获取所有包含详细信息的项目,我使用带有嵌套订阅和 forEach 循环的代码:

getInvoices() {
    this.invoiceService.getInvoiceForResidence().subscribe(res4 => {

      // invoice list
      this.invoices = res4;

      // invoice details
      this.invoices.forEach(inv => {
        this.invoiceService.getInvoicePreview(inv.fakturaId).subscribe(res5 => {
          inv.InvoicePreview = res5;
        });
      });
    });
  }

“InvoicePreview”是“invoices”的一个键,所以之后我有一个数组,我可以使用 *ngFor 在 HTML 中简单地呈现所有项目的详细信息

有没有更好的方法来做同样的事情但没有嵌套订阅?如果一个有很多项目,那么应用程序的工作速度很慢。

标签: angularrxjsobservablesubscribe

解决方案


要将许多网络请求组合在一起并避免嵌套订阅(一种反模式),我建议您使用forkJoinand concatMap。forkJoin 允许您对 observables 进行分组,并且concatMap是一个扁平化运算符

// getInvoices() {
//     this.invoiceService.getInvoiceForResidence().subscribe(res4 => {

//       // invoice list
//       this.invoices = res4;

//       // invoice details
//       this.invoices.forEach(inv => {
//         this.invoiceService.getInvoicePreview(inv.fakturaId).subscribe(res5 => {
//           inv.InvoicePreview = res5;
//         });
//       });
//     });
//   }

import { of, forkJoin, Observable } from 'rxjs'; 
import { tap, concatMap } from 'rxjs/operators'

let invoices = [];

function getInvoices() {
  // Mock your invoices
  const getInvoiceForResidence = of([{fakturaId: "invoice 1"}, {fakturaId: "invoice 2"}, {fakturaId: "invoice 3"}])
  const getInvoicePreview = (id: string) => of('preview from ' + id)

  return getInvoiceForResidence.pipe(
    tap((invoices) => invoices = invoices),
    concatMap((invoices ) => {
      const networkRequestsToMake: Observable<string>[] = invoices.map(invoice => getInvoicePreview(invoice.fakturaId))
      return forkJoin(...networkRequestsToMake)
    })
  )
}

getInvoices().subscribe(signal => {
  console.log(signal)
})


请在此处复制并粘贴此代码:https ://stackblitz.com/edit/rxjs-koqtab?devtoolsheight=60

这是一些关于分叉加入的信息 https://www.learnrxjs.io/operators/combination/forkjoin.html

我建议您观看此视频并完整阅读本文以了解如何使用展平运算符。

https://medium.com/@shairez/a-super-ninja-trick-to-learn-rxjss-switchmap-mergemap-concatmap-and-exhaustmap-forever-88e178a75f1b

如果您需要更多帮助或澄清,请告诉我。


推荐阅读