Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Transforming Observable with .map

I have a problem with transforming my observable. Details below:

I have a data like this

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

Then I get this data from api:

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

Then, I'm trying to subscribe this:

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

And It's ok, it's working. But I need to modify the structure of object and I would like to use .map to transform received object to this schema:

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

.. and nothing working for me.. :/ Even if I don't want to add new property, but modify a value on for example firstName:

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

it's not working (Type 'string' is not assignable to type 'Data[]', I know what it means, but I don't know how to do that, where is my mistake?)

like image 846
Przemo Avatar asked Dec 02 '22 11:12

Przemo


1 Answers

There's a difference between map operator in Observable and map method of array. You want to transform the result of HTTP request to array and then apply some additional transformation to every member of that array. Let's go step by step.

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

This returns the Observable object, which holds the Response of angular's Http service. To make use of the data inside of it, you have to call Response's json() method.

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

This code means 'when the observable sends some data, put it into a processing pipe. Treat it as HTTP response and extract its content as JSON, then put to another Observable'. So if you subscribe to it, you'll get your array.

Then you can do anything with that regular array, like using its map method. Let me use my own example though it's very similar to yours.

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

     this.persons = modifiedArray;
});

Or, if you like to, manipulate array items before subscription:

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

Two consecutive map operators in pipe can be replaced with a single one:

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;
});

If it's too wordy to you, here's a more compact (but less readable) version:

this.http.get('...')
.pipe(map(response => response.json().map(item => item.newProperty = 'value')))
.subscribe(persons => this.persons = persons);
like image 150
Anton Rusak Avatar answered Dec 05 '22 15:12

Anton Rusak