【问题标题】:Transforming Observable with .map使用 .map 转换 Observable
【发布时间】:2018-02-22 03:30:45
【问题描述】:

我在转换我的 observable 时遇到问题。详情如下:

我有这样的数据

[
    {
      'firstName': 'John',
      'lastName': 'Cash',
      'age': 20
    }
  ];

然后我从 api 获取这些数据:

  public getData(): Observable<Data[]> {
    return this.http.get('xxx')
    .map(
      response => response.json()
    );
  }

然后,我正在尝试订阅:

this.service.getData.subscribe(
        (res) => this.data = res
      );

没关系,它正在工作。但是我需要修改对象的结构,我想使用 .map 将接收到的对象转换为这个模式:

[
    {
      'firstName': 'John',
      'lastName': 'Cash',
      'age': 20,
'newProperty': 'value'
    }
  ];

.. 对我没有任何作用.. :/ 即使我不想添加新属性,但要修改一个值,例如 firstName:

  .map(
    return x => x[0].firstName = 'asd'
  )

它不起作用(类型'string'不能分配给类型'Data[]',我知道它的意思,但我不知道该怎么做,我的错误在哪里?)

【问题讨论】:

  • 我在重新调整之前需要创建该类型的对象
  • 但是没有创建新对象?例如,通过具有新属性的数据(无类型)创建全新的对象数组?也许具有传播功能。也许它没有任何意义.. 或者也许我不需要修改结构,也许有可能将变量添加到 .map 并为 observable 的每个元素复制不同的值?
  • 例如,新变量将是 fullName,数据来自 firstName 和 LastName。

标签: rxjs observable


【解决方案1】:

Observable 中的map 操作符和数组的map 方法是有区别的。您希望将 HTTP 请求的结果转换为数组,然后对该数组的每个成员应用一些额外的转换。让我们一步一步来。

this.http.get('...')

这会返回 Observable 对象,该对象持有 Angular 的 Http 服务的 Response。要使用其中的数据,您必须调用 Response 的 json() 方法。

.pipe(
  map((response:Response) => response.json())
)

这段代码的意思是'当 observable 发送一些数据时,将其放入处理管道。将其视为 HTTP 响应并将其内容提取为 JSON,然后放入另一个 Observable'。因此,如果您订阅它,您将获得您的数组。

然后你可以用这个常规数组做任何事情,比如使用它的 map 方法。让我用我自己的例子,虽然它和你的很相似。

this.http.get('...')
.pipe(map((response:Response) => response.json()))
.subscribe((array:Person[]) => {
     let modifiedArray = array.map((item:any) => {
           item.newProperty = 'value';
     }

     this.persons = modifiedArray;
});

或者,如果您愿意,可以在订阅前操作数组项:

const modifiedData$:Observable<Person> = this.http.get('...').pipe(
  map((response:Response) => response.json()),
  map((array:Person[]) => {
     return array.map((item:Person) => {
           item.newProperty = 'value';
     }
)};

管道中两个连续的 map 运算符可以替换为一个:

const modifiedData$:Observable<Person[]> = this.http.get('...')
  .pipe(map((response:Response) => {
     return response.json().map((item:Person) => {
       item.newProperty = 'value';
     }
  });

modifiedData$.subscribe((persons:Person[]) => {
     this.persons = modifiedArray;
});

如果对您来说太罗嗦,这里有一个更紧凑(但可读性较差)的版本:

this.http.get('...')
.pipe(map(response => response.json().map(item => item.newProperty = 'value')))
.subscribe(persons => this.persons = persons);

【讨论】:

  • 有意义,除了地图函数在 Observable 上不存在。不知道我有什么版本的 rxjs。
  • 从 5.5 版开始,像 map 这样的 rxjs 运算符成为纯函数,应该在管道内使用。编辑了我的答案。
  • 啊,是的,用管道做这件事也对我有用。我忘了在这里写一些关于那个工作的东西。
  • @Anton Rusak,你介意看看我的帖子。我有类似的东西。我尝试了上述解决方案,但效果不佳。 stackoverflow.com/questions/62205181/…
【解决方案2】:

你必须创建该类型的对象,例如如下

.map((res: Response) => res.json().map(obj => new MyObject(obj.id, obj.name)))

【讨论】:

    猜你喜欢
    • 2018-09-12
    • 1970-01-01
    • 1970-01-01
    • 2021-10-02
    • 2020-04-02
    • 2019-03-24
    • 2021-05-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多