1

I'm pretty new to angular and rxjs and I just can't get it solved. I know my code is wrong, but i don't know how to write it correctly.

I'm fetching a JSON via a HTTP Request, the JSON contains data in an array. After that i want to loop through the array inside the JSON data and fetch additional data of another HTTP Endpoint.

I looked into flatMap, switchMap, and so on and I can't figure to combine these commands in my case.

Thank you guys!

My Code so far:

  checkMatches() {
    this.http.get<{
      message: string,
      result: any}>
    (BACKEND_URL + 'matches')
        .pipe(map((matchData) => {
          return {matches: matchData.result.map(match => {
            this.userService.getUserData(match.matchedUser).subscribe(userData => {
              console.log(userData);
            }
              );
            return {
              id: match._id,
              matchedUser: match.matchedUser,
              firstMatch: match.firstMatch,
              name: userData.userName,
              img: userData.userImg,
              status: match.status,
            };
          })};
        }))
        .subscribe(transformedMatchData => {
        console.log(transformedMatchData);
        });
  }
  • It looks like you are looping over an array and doing HTTP calls in each loop, can you specify all your requirement in a better way? – Ashish Ranjan May 11 '20 at 14:16
  • @AshishRanjan That's correct. The first http call gives me a JSON like this: {message: sometext, matches: [{id:xxx, status,:xxx, userId: xxx}]. To complete my data I need the additional data (the username and imageUrl) of the "getUserData" which is also a HTTP request. – BennyVenassi May 11 '20 at 14:24

1 Answers1

1

As mentioned in comment below, you should re-think about this architecture, you should have a way to get all these records in one/two requests, not to fire 'N' requests if your loop length is 'N'.

Answering for the original posted question:

It looks like for every reponse of matches, you need to query APIS, you can use swicthMap() along with forkJoin here:

Using switchMap would merge (BACKEND_URL + 'matches') say Parent observable url observable along with next observables we create with its result, and also, it cancels new requests of if parent observable emits again.

Using forkJoin would make you wait for all the child observables to complete before emitting data.

checkMatches() {
    this.http.get<{
    message: string,
    result: any}>
    (BACKEND_URL + 'matches')
        .pipe(switchMap((matchData) => {
            return forkJoin(
                ...matchData.result.map(match => {
                    return this.userService.getUserData(match.matchedUser).pipe(
                        map((userData) => {
                            return {
                                id: match._id,
                                matchedUser: match.matchedUser,
                                firstMatch: match.firstMatch,
                                name: userData.userName,
                                img: userData.userImg,
                                status: match.status,
                            };
                        })
                    )
                })
            )
        }))
        .subscribe(transformedMatchData => {
            console.log(transformedMatchData);
        });
}
Ashish Ranjan
  • 12,760
  • 5
  • 27
  • 51
  • 1
    I upvoted because you've provided a viable solution but I agree with your comment on his OP - this should be architechted differently so as not to require so many trips over the wire. Seems like all of this data could be fetched with a single GET. – Blair Holmes May 11 '20 at 14:31
  • @BlairHolmes Yes, that is correct so many requests should not go for a single GET – Ashish Ranjan May 11 '20 at 14:50
  • 1
    @AshishRanjan thank you a lot, this works fine! Mhh, okay, and maybe i should change the serversided code then, to capture the userdata there. – BennyVenassi May 11 '20 at 15:09