angular - 如何使用 RxJS 并行化多个 HTTP 调用

标签 angular typescript rxjs

背景

我正在构建一个 Angular 应用程序,其中列出了在给定地址注册的公司。

给出一些上下文......

假设我有 x3 个公司:公司 A、公司 B 和公司 C。

B 公司的注册地址与 A 公司相同。C 公司不是。

当我导航到应用程序并筛选公司 A 时,我希望在列表中只看到公司 B。

问题

我的问题不是我不能让它工作,它太慢了!我需要以某种方式利用多线程/并发。

为了确定在给定地址注册了哪些公司,我必须进行多次 HTTP 调用。

在解释我进行 HTTP 调用的顺序之前。让我向您展示 API 的样子:

GET /api/companies/CompanyA/address
{
  id: 1,
  addressLine1: '123 Some street',
  ...
}

GET /api/companies/CompanyA/links
[
  {id: 2, name: 'Company B'},
  {id: 3, name: 'Company C'},
]

对了,顺序是这样的:

  1. 获取公司 A 的地址并存储 ID
  2. 获取公司 A 的链接
  3. 遍历每个链接 3a.获取链接地址 3b.检查地址 ID 是否与公司 A 的地址 ID 匹配。如果是,请存储链接。

当前实现

const companyAId: number = 1;    

const companyAAddress: Object = await this.httpService.getAddress(companyAId).toPromise();

const companyALinks: Object[] = await this.httpService.getLinks(companyAId).toPromise();

const companiesToShow: Object[] = [];
for (let link of links) {
    const linkAddress: Object = await this.httpService.getAddress(link ['id']).toPromise();
    if (linkAddress['id'] === companyAAddress['id']) companiesToShow.push(link );
}

一定有更优雅/更高效的解决方案!

任何帮助将不胜感激:)

谢谢,

最佳答案

您是正确的,每个 API 调用都必须先等待另一个调用完成。

您本身无法访问多线程,但您可以在编写时使用 Promise.all 使其并发。具体来说,您可以同时检索地址和链接,然后同时检索所有其他地址。我已经缩短了一些方法调用名称以使其更易于编写:

const [companyAAddress, companyALinks] = await Promise.all(
  getAddress(id).toPromise(),
  getLinks(id).toPromise(),
);

const companiesToShow = await Promise.all(links.map(link => getAddress(link.id).pipe(
  map(linkAddress => [link, linkAddress]),
  filter(([, { id }]) => id === companyAAddress.id),
).toPromise())

除了使用 promises 之外,您还可以严格使用 Observables 来做到这一点,这将使它可以取消。

forkJoin(getAddress(id), getLinks(id)).pipe(
  mergeMap(([companyAAddress, companyALinks]) => companyALinks.map(link => getAddress(link.id).pipe(
    map(linkAddress => [link, linkAddress]),
    filter(([, { id }]) => id === companyAAddress.id),
  ))
)

但是,我会说从单个请求中获取链接公司的能力应该由服务器实现。

关于angular - 如何使用 RxJS 并行化多个 HTTP 调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52391098/

相关文章:

arrays - 如果最长的表的长度大于或等于5,如何将每个表的长度更改为等于最长的表的长度?

javascript - 我可以将类字段链接到orientdb中的多个类吗?

angular - 如何测试 Angular - catchError 运算符 'rxjs'

typescript - 使用 TypeScript 从 Angular2 中的 http 数据链接 RxJS Observables

javascript - 观察者订阅不会在第一次加载到组件时触发

Angular 4 Portal/CdkPortal 在新的子窗口中不工作

javascript - AngularJS 到 Angular - NgUpgrade

angular - 动态设置路由器 socket 名称

typescript :声明函数类型的等效方式?

typescript - 如何创建泛型类类型作为另一个类型的子集