使用 RxJS 从多个 API 调用构建数据

2024-02-18

我试图更好地了解如何使用 RxJS 运算符来解决我遇到的特定问题。我实际上有两个问题,但它们很相似。

我正在从 API 端点获取一堆文档/api/v3/folders/${folderId}/documents我已经设置了具有执行此操作的功能的服务,并处理所有身份验证等。

然而,这个文档对象数组确实not具有描述属性。为了获得描述,我需要打电话/api/v3/documents/${documentId}/上次通话中的每个文档。我的文档界面如下所示:

export interface Document {
  id: number;
  name: string;
  description: string;
}

我想我需要使用mergeMap等待并获取文档一些如何将描述添加到我的Document接口并返回整个内容,但是我无法获得最终结果。

getDocuments(folderId: number) {
    return this.docService.getDocuments(folderId, this.cookie).pipe(
      map(document => {
        document; // not entirely sure what to do here, does this 'document' carry over to mergeMap?
      }),
      mergeMap(document => {
        this.docService.getDocument(documentId, this.cookie)
      }) // possibly another map here to finalize the array? 
    ).subscribe(res => console.log(res));
  }

这可能看起来有点重复,但我发现的任何帖子都没有 100% 为我解决问题。

对于理解如何在第二次调用中正确使用数据并将其全部包装在一起的任何帮助都非常重要much赞赏。谢谢。

感谢@BizzyBob,这是经过编辑和解释的最终解决方案:

  getDocuments(folderId: number) {
    const headers = new HttpHeaders({
      'Content-Type': 'application/json',
      'Context': this.cookie$
    });
    return this.docService.getDocuments(folderId, this.cookie$).pipe(
      mergeMap(documents => from(documents)),
      mergeMap(document => this.http.get<IDocument>(
        this.lcmsService.getBaseUrl() + `/api/v3/documents/${document.id}`,
        { headers: headers }
      ).pipe(
        map(completeDoc => ({...document, description: completeDoc.description}))
      )),
      toArray()
    ).subscribe(docs => {
      this.documents = docs;
      console.log(this.documents);
    }
    )
  }

由于某种原因我无法pipe()从第二次服务订阅开始,所以我最终不得不做出http.get打电话到那里。错误是“无法在类型订阅上使用 pipeline()”,这有点令人困惑,因为我正在使用pipe()在第一次订阅时。我将此更改应用到我的服务功能中,该功能更新了行为主题,并且运行完美。谢谢!


有几种不同的方法可以从多个 api 调用中组合数据。

我们可以:

  • use from将每个项目单独发送到流中
  • use mergeMap订阅辅助服务调用
  • use toArray一旦所有单独的调用完成后发出一个数组
  getDocuments() {
    return this.docService.getDocuments().pipe(
        mergeMap(basicDocs => from(basicDocs)),
        mergeMap(basicDoc => this.docService.getDocument(basicDoc.id).pipe(
          map(fullDoc => ({...basicDoc, description: fullDoc.description}))
        )),
        toArray()
    );
  } 

我们还可以利用forkJoin:

  getDocuments() {
    return this.docService.getDocuments().pipe(
      switchMap(basicDocs => forkJoin(
        basicDocs.map(doc => this.docService.getDocument(doc.id))
      ).pipe(
        map(fullDocs => fullDocs.map((fullDoc, i) => ({...basicDocs[i], description: fullDoc.description})))
      )),
    );
  }

这是一个工作堆栈闪电战 https://stackblitz.com/edit/so-64284681?file=src/app/app.component.ts

另外,您可以考虑将流定义为变量documents$与方法相反getDocuments().

  documents$ = this.docService.getDocuments().pipe(
    mergeMap(basicDocs => from(basicDocs))
    mergeMap(basicDoc => this.docService.getDocument(basicDoc.id).pipe(
      map(fullDoc => ({...basicDoc, description: fullDoc.description}))
    ))
    toArray()
  );
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 RxJS 从多个 API 调用构建数据 的相关文章

随机推荐

  • 将我的应用程序推送到 Heroku 时,为什么会收到错误 500“我们很抱歉,但出了点问题”?

    我将我的应用程序推送到 Heroku 并收到 我们很抱歉 但出了点问题 500 为什么是这样 我知道错误消息来自 public 目录中我自己的文件之一 标题为 500 html 但我不确定为什么会发生这种情况 我的 heroku 日志以及我
  • apache Spark sql 中的缓存表

    来自 Spark 官方document http spark apache org docs latest sql programming guide html caching data in memory 它说 Spark SQL 可以通
  • 如何在 Javascript 循环中重新绘制 HTML 元素?

    我有一些 Javascript 可以在 HTML 元素上 动画 颜色变化 如下所示 var element document getElementById someid while i lt 255 element style color
  • 仅通过 GDI+ 和 DotNet 指定大小来创建 Dib

    我最近刚刚发现 GDI 中不同构造函数之间的差异 去 var bmp new Bitmap width height pixelFormat 创建 DDB 设备相关位图 而 var bmp new Bitmap someFile 创建 DI
  • 字符串必须正好是一个字符长

    我有一个我认为很简单的问题 由于某种原因 以下代码生成异常 字符串必须恰好是一个字符长 int n 0 foreach char letter in charMsg Get the integral value of the charact
  • 2D 循环卷积与卷积 FFT [Matlab/Octave/Python]

    我试图理解 FTT 和卷积 互相关 理论 因此我创建了以下代码来理解它 代码是 Matlab Octave 但我也可以用 Python 来完成 In 1D x 5 6 8 2 5 y 6 1 3 5 1 x1 x zeros 1 4 y1
  • Android DataBinding 泄漏内存

    我正在使用数据绑定并且我已经声明了lateinit var对于绑定以及当我要使用不同的片段 Leaky canary 显示泄漏时 Fragment class HomeFragment BottomNavViewHostBaseFragme
  • SemaphoreSlim.WaitAsync 延续代码

    我的理解await关键字是下面的代码await合格的语句在完成后将作为该语句的延续运行 因此以下两个版本应该产生相同的输出 public static Task Run SemaphoreSlim sem TraceThreadCount
  • VSCode 中的 Python 路径

    我在 Mac OSX 10 14 2 上安装了 Anaconda 发行版 有了它 我安装了 VSCode 我将用它来编写 python 脚本 最近 我更新了 Anaconda 中的一些环境 VSCode 用于其集成终端的 python 路径
  • 为不同语言生成不同的 docpad 集合

    我想调整我的多语言 DocPad 博客 以便以 ru md 结尾的页面进入 ru 目录 以 en md 结尾的页面进入 en 目录 假设这是初始结构 src pages page1 ru md page1 en md page2 ru md
  • 如何检查json数组是否有值?

    我正在使用条件 if obj2 getString patronCheckoutInfo equals null 但它不适用于数组获取值的情况 例如 情况 1 当 json 获取 patronCheckoutInfo 的值时 ErrorMe
  • Python中的时间范围重叠算法

    我有一个包含不同 ID 开始日期和结束日期的列表 让我们说 5 d datetime 2010 9 19 0 0 0 d datetime 2010 9 19 0 5 10 6 d datetime 2010 9 19 0 0 0 d da
  • 如何在远程存储库上运行 Git 命令

    我正在尝试编写一个简单的 PHP 应用程序 它将使用终端命令从远程 Git 存储库检索一些信息 我不想创建本地工作副本或存储库 我只想从远程存储库读取信息 浏览树 提交历史记录 文件差异 下载文件 因此它将是只读连接 我需要做的是运行一系列
  • 标准加密文件格式有哪些?

    我对加密文件格式有点困惑 假设我想使用 AES 256 加密文件 我通过加密算法运行该文件 现在有了一个加密字节流 显然 我可以将该字节流写入文件 但任何第三方加密应用程序都不会理解它 因为它不期望只是原始的加密字节流 我可以将其写入什么文
  • 控制台应用程序中的命令行当前工作目录[重复]

    这个问题在这里已经有答案了 可能的重复 如何找出我的控制台应用程序在 C 中运行的目录 https stackoverflow com questions 97312 how do i find out what directory my
  • 如何对齐和居中输入字段?

    我有一个 HTML 表单 输入字段已经居中 但它们没有垂直对齐 我想让所有标签和输入垂直对齐 以便所有标签都在同一垂直线上 并且所有输入都在同一垂直线上 到目前为止 我所拥有的只是 div 内的字段 div class container
  • 更好的 Django 管理 ManyToMany 字段小部件

    我找到了 Django Admin 的默认设置models ManyToManyField小部件使用起来很麻烦 这是HTML 选择 http www htmlcodetutorial com forms SELECT MULTIPLE ht
  • mysql.server 启动时出现 PID 错误?

    我刚刚尝试使用自制程序 在 Mac OS X 10 6 上 安装 MySQL 但我在第一个障碍时遇到了问题 当尝试手动启动服务器 mysql server start 时 出现以下错误 ERROR Manager of pid file q
  • 在 CSS 中将内部 div 与右下对齐

    将我的内部 div 放在右下角的最简单方法是什么 div style width 200px height 200px border 3px FF6666 solid div style font weight bold text alig
  • 使用 RxJS 从多个 API 调用构建数据

    我试图更好地了解如何使用 RxJS 运算符来解决我遇到的特定问题 我实际上有两个问题 但它们很相似 我正在从 API 端点获取一堆文档 api v3 folders folderId documents我已经设置了具有执行此操作的功能的服务