0

In one of my route resolver, I want to get a list of Animals (Animal[]) returned by an API Call. For each animal, I need an extra API call to get the breed name. I tried this :

return this.apiService.get('/api/v1/website/' + environment.web_id + '/useraccount/' + user.id + '/animal').pipe(
  map(animals => animals.map(animalObs => {
    // return animalObs;
    return animalObs.pipe(
      map((animal: Animal) => {
        animal.ani_breed = this.breedService.get(animal.anb_id).pipe(
          map(breed => {
            return breed.anb_name;
          })
        );
        return animal;
      }),
    );
  })),
);

But I get an error when compiling : Type 'Observable' is not assignable to type 'string'. [2322]

I think I am missing something... Please help!

2 Answers 2

7

The actual implementation depends on whether you want to run requests in sequence or in parallel but you can do it example like the following:

this.apiService.get('/api/v1/website/' + environment.web_id + '/useraccount/' + user.id + '/animal').pipe(
  mergeMap(animals => {
    const animals$ = animals.map(animal => this.breedService.get(animal.anb_id).pipe(
      map(breed => {
        animal.ani_breed = breed;
        return animal;
      })
    ))

    return forkJoin(...animals$);
  }),
);
Sign up to request clarification or add additional context in comments.

Comments

2

I think what you need is a mergeMap which merge your current request to another request that will request all the returned animals using forkJoin and combine it together.

  getAnimals = () => this.apiService.get('/api/v1/website/' + environment.web_id + '/useraccount/' + user.id + '/animal').pipe(
    mergeMap(animals =>
      Observable.create((observer: Observer<any[]>) => {
        const animals$ = animals.map(
          animal => this.breedService.get(animal.anb_id).pipe(
            map(breed => {
              return {
                ...animal,
                breed_name: breed.anb_name
              }
            })
          )
        );

        forkJoin(animals$).subscribe(result => {
          observer.next(result);
          observer.complete();
        });
      }))
  );

More about forkJoin and mergeMap

https://www.learnrxjs.io/operators/combination/forkjoin.html

https://www.learnrxjs.io/operators/transformation/mergemap.html

EDIT

What you want to do to get the animal and its breed name is return all of the animals property using spread operator and assign the bread name next to it.

        map(breed => {
          return {
            ...animal,
            breed_name: breed.anb_name
          }
        })

FINAL EDIT

Spread operator allows you to enumerate all of the objects property. it has the same output as the code below but in a different procedure.

  map(breed => {
    animal.breed_name = breed.anb_name;
    return animal;
  })

4 Comments

Hi @Riyens, thanks for your reply. Doing this just give me the breeds name as result
@LouisRocher thats what i see on your implementation. may i know what is your expected output?
I want to have a array of animals with the breed_name as a string one the animal object. Thanks for your time
Updated. I hope everything i explained make sense/understand so other ppl can apply it also when they encounter the same problem

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.