【问题标题】:Not getting expected result from RxJS map() operator with Angular HttpClient使用 Angular HttpClient 未从 RxJS map() 运算符获得预期结果
【发布时间】:2022-08-21 20:29:23
【问题描述】:

我想了解 RxJS 的 map() 运算符。

以下是按预期工作的示例之一。在此示例中,所有名称都将一一附加文本学生。

studentArray:string[]=[\'sam\',\'robert\',\'lisa\'];
from(this.studentArray).pipe(map((s:string)=>s=s+\' student\')).subscribe(d=>console.log(d));

现在我有下面的示例代码。使用此代码,我正在调用一个返回 ToDo 对象数组的服务。我想要做的是迭代每个 ToDo 对象并返回更新的对象

但是当我这样做时,它给出了一个错误,错误的原因是map 运算符中的data 变量。在上面的示例中,地图运算符没有获取 ToDo 数组的单个元素,而是将整个数组传递给地图。

我在这里做错了吗?

编辑:更新的图像。

  • 没有分配的地图可能应该类似于.pipe(map(data => data.title + \'append\')).subscribe(...)map 管道也会给你一个数组。如果要映射数组项,则必须在映射管道内执行.pipe(map(data => data.map(item => ....)))
  • @JasonWhite这里的问题是字符串数组的功能与自定义对象数组的功能不同。请参阅我的字符串示例。我想对自定义数组对象做同样的事情。
  • 提示:内联代码格式 (like this) 只需要单个反引号。只有块格式化才需要三个反引号的“代码围栏”。

标签: angular rxjs rxjs-observables


【解决方案1】:

您使用的 map() 函数不是 JavaScript 标准 Array.map,它是 RxJs map 运算符,它将项目函数应用于发出的每个值(在您的情况下,单个值是 ToDo 的数组) 由源 Observable 发出,并将结果值作为 Observable 发出。

【讨论】:

  • 感谢您的澄清。但在那个理论中,当我使用与字符串数组相同的 RxJS 映射运算符时,它的工作正常。请参阅我在问题中的示例。
  • 在字符串数组示例中,您使用from 运算符发出该数组的项,然后使用map 运算符连接每个发出的项的“学生”。 rxjs.dev/api/index/function/from
【解决方案2】:

每个人都说这不是 Angular 的东西,但它更像是一个 Typescript 编译器问题。它正在正确地告诉您您正在将type B 的某些内容分配给type C 的其他内容。在我们这里的例子中,您正在将一个字符串分配给一个 TODO 数组。

@Jason White 在评论中提到的是 IMO 解决您问题的正确答案。

【讨论】:

    【解决方案3】:

    您错误地使用了map 运算符。 map 运算符接收一个值,对其进行转换,然后返回转换后的值。你正在做一个作业。一个有效的例子是:

    .pipe(
       map((value: string) => value + 'append')
    )
    

    此外,您的data 不是单个ToDo,而是一个数组,即ToDo[]。因此,对于data = data.title + 'append',您正在尝试将string 分配给ToDo[]

    如果我理解正确,您想在每个ToDotitle 属性上附加一些内容。然后你必须做这样的事情:

    this.http.get<ToDo[]>('YOU-ENDPOINT-URL-HERE').pipe(
       concatMap((dataArray: ToDo[]) => from(dataArray)), // from array to single objects
       map((data: ToDo) => {
          data.title += 'append'; // transform tittle
          return data; // return transformed data
       }),
       toArray() // recreate array
    ).subscribe((d) => console.log(d));
    

    编辑:您的第一个示例不等同于您的用例。 from 运算符接受一个数组,在您的示例中为 string[],并将其转换为 Observable&lt;string&gt;

    http.get&lt;Todo[]&gt; 声明从后端返回的类型将是一个数组。这是将传递给您的管道的数据类型,因此也将传递给您的map 运算符。

    【讨论】:

    • 更新截图。是的,我想更新数组中每个自定义对象的标题。这里的问题是为什么传递给 map 的数据是一个数组。在问题中查看我类似类型的示例。这适用于地图,但当我尝试对自定义对象数组执行相同操作时,它不起作用。
    • @RaviKhambhati 请参阅我的编辑部分。另一方面,您在更新的屏幕截图中也错误地使用了map 运算符。请重新阅读我的答案。
    【解决方案4】:

    关注@Vasileios Kagklis 的回答。他解释了你的问题。 rxjs map 管道与 JavaScript 高阶 map 函数完全不同。您不应该在map 管道中使用= 分配值。

    我不是 100% 确定你想用这个来完成什么,但据我所知,你可能正在寻找类似......

    this.http.get<ToDo[]>(`....`)
      .pipe(
        map(data => data.map(todo => ({
           ...todo,
           title: todo.title + 'append'
         })
      )
      .susbscribe(todos => console.log(todos));
    

    所以map rxjs 管道接收到ToDo[],所以dataToDo[] 而不是单个ToDo。因此,一旦发出数据,您就必须遍历该数组并改变数组中的每个项目(JavaScript 的高阶 map 函数)以更新标题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-02-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-25
      • 2019-04-28
      • 1970-01-01
      相关资源
      最近更新 更多