marcwa93
marcwa93

Reputation: 13

How to load additional data for a collection with rxjs

I'm struggeling to understand the different rxjs operators. For example when i've got a collection of objects and i want to add additional data from an api to each object.

e.g.

people = [{id: 1, name: null}, {id:2, name: null}]
from(people).pipe(
  map(person => {
    return api.getName(person.id).pipe(
      map(name => person.name = name)
    )
  })
).subscribe(people =>
  console.log(people) // should be [{id: 1, name: bob}, {id:2, name: alice}]
)

I tried using mergeMap, map, switchMap in different variations but i never figured out how to get map the additional data into the array.

Upvotes: 1

Views: 607

Answers (2)

Eliseo
Eliseo

Reputation: 57941

If you want a list, I think do you need use forkJoin. You map each element of people to a call

people = [{id: 1, name: null}, {id:2, name: null}];
forkJoin(people.map(p=>this.api.getName(person.id))
    .subscribe((res:any[])=>{
       res.forEach((p:any,index)=>{
         people[index]={...people,..p}
       })
    })

Well you can use map too to get the response with the full elements

people = [{id: 1, name: null}, {id:2, name: null}];
forkJoin(this.people.map(p=>this.api.getName(p.id))).pipe(
   map((res:any[])=>{
       const result=this.people.map((p,index)=>
         //if the response is an object map to
         //({...p,...res[index]})
         //if the response is a string,
         ({...p,name:res[index]}) 
       )
       return result
    })
).subscribe(res=>{console.log(res)})

Upvotes: 0

cjd82187
cjd82187

Reputation: 3593

Your issue is likely when you are using map/switch map you are returning the result of the assignment person.name = name;

When you use an arrow function without curly braces like this

() => something;

It is actually shorthand for

() => {
  return something
}

Here is a working example, with some sloppy class creation to make it work... https://stackblitz.com/edit/angular-ivy-xfunnc?file=src%2Fapp%2Fapp.component.ts

  people = [{id: 1, name: null}, {id:2, name: null}];
  peopleWithNames = from(this.people).pipe(
    switchMap(person => {
      return this.api.getName(person.id).pipe(
        map(name => {
          // set the person's name property
          person.name = name;
          // but return the whole person object, not just the retrun from the assignment
          return person;
        })
      )
    })
  ).subscribe(p => {
    console.log(p)
  })

Upvotes: 4

Related Questions