MarcoLe
MarcoLe

Reputation: 2509

RXJS Observables - http call for each index value and merge result

I do a http call to get an Array with objs. And now I want to call for each objs that return me an ID another http call. After all I want to have one observable result.

So far I managed to get for each index a http call. The problem instead of one result I got multiple.

getStats(tag: string) {
    return this.service.getClanByClanTag(tag)
        .map(clan => {
            return clan.memberList; //the arr that return the ID's
        })
        .switchMap((member: PlayerByMemberListType[]) => {
            return member; // singleObj of the arr
        })
        .concatMap((singleMember) => {
            return this.service.getPlayerData(singleMember.tag).map(player => {
                //push data to the new arr which should return only one time
                this.newArr.push({
                    tag: singleMember.tag,
                    name: singleMember.name,
                    warStars: player.warStars,
                    trophiesNightBase: singleMember.versusTrophies
                });
                return this.newArr;
            });
        });
}

This is what the console prints out after subscribing to it:

Array [ {…} ]
Array [ {…}, {…} ]
Array(3) [ {…}, {…}, {…} ]
Array(4) [ {…}, {…}, {…}, {…} ]
Array(5) [ {…}, {…}, {…}, {…}, {…} ]
...

I know I need some kind of Observable.forkJoin but I don't know how integrate it in the code.

Upvotes: 0

Views: 1218

Answers (2)

CozyAzure
CozyAzure

Reputation: 8468

So basically what you want to achieve is this.

  1. Get the clan info
  2. Using clan info from step 1, get the memberList in the clan
  3. For each member inside the memberList, get the players

You will need to think of a way to preserve the info at step2 when before switchMap in step3. Usually we will use a Subject, but in the case if you do not want to, simply map the Observable to preserve the data:

getStats(tag: string) {
    return this.service.getClanByClanTag(tag)
        .map(clan => {
            return clan.memberList; //the arr that return the ID's
        })
        .switchMap((memberList: PlayerByMemberListType[]) => {
            //note that the following map is a function of javascript array, not Observable
            //it returns an array
            let arrayOfObservables = memberList.map(singleMember => {
                this.service.getPlayerData(singleMember.tag)
                //map the data so as to preserve the data of singleMember 
                //by creating a new object, using Object.assign
                    .map(playerData => {
                        return Object.assign({memberData: singleMember}, playerData,)
                    });
            })
            return Observable.forkJoin(arrayOfObservables);
        })
        .map(players => {
            //players is an array of Object that is the format of {memberData:singleMember, playerData:player)
            //perform Object destructuring method
            return players.map(({memberData,playerData}) => {
                return {
                    tag: memberData.tag,
                    name: memberData.name,
                    warStars: playerData.warStars,
                    trophiesNightBase: memberData.versusTrophies
                }
            })
        })
}

Upvotes: 0

Fabricio
Fabricio

Reputation: 7925

Try something like this:

this.service.getClanByClanTag(tag)
    .mergeMap(clan => clan.memberList)
    .mergeMap(
        member => this.service.getPlayerData(member.tag), // supposedly this returns an observable
        (member, player) => ({ 
            tag: member.tag,
            name: member.name,
            warStars: player.warStars,
            trophiesNightBase: member.versusTrophies
        })
    )
    .toArray()

Upvotes: 1

Related Questions