-1

I have 3 APIs. API 1: returns an object, that object has a GalleryImages field. The Items field is an array of string IDs.

API 2: will use the network string ID from API 1 to call. API 2 returns an object, in the object there is an Items field. The Items field is an array of objects, with each Object being the AssetIds field, the AssetIds field is an array of string IDs.

API3: For each element of the Items field taken from API 2. will pass that list ID to API 3, the output of API 3 is an object, that object has an Items field, This Items field is an array of an object, that object has URL field.

So with this form, what RXJS operations will I combine to produce a result in the form of an Object with fields: Title: string (this field is taken from the title field from API1 Images: this field is an array of URLs taken from API3

Everyone help me. Thank you everyone for reading.

enter image description here

Demo model: https://drive.google.com/file/d/1QpdvtsWFzhxUVx1Z760qWkQKmCiXD3Wp/view?usp=sharing

my solution looks bad, and it will fail if i don't handle all exceptions e.g. null, etc

public getGalleryImagesContentDtoObservableByIds(ids: string[]): Observable<any[]> {

    const obs = new Subject<ImageGalleryComponentDto[]>();
    const listResult: ImageGalleryComponentDto[] = [];

    if (ids && ids.length > 0) {
      this.galleryImagesService.queryGalleryImagesContent({ ids: ids.join(",") }).subscribe(a => {
        a.items.forEach(b => {
          const listGalleryImage = b.data.Images;

          if (listGalleryImage && listGalleryImage['iv'] && listGalleryImage['iv'].length > 0) {
            this.galleryImageService.queryGalleryImageContent({ ids: b.data.Images['iv'].join(",") }).subscribe(c => {

              const item = new ImageGalleryComponentDto();
              item.title = b.data.Title[this.languagueService.languague];
              item.id = b.id;
              item.tag = b.data.Tag[this.languagueService.languague];

              const listImageDtoObs = c.items.map(d => {
                const listImage = d.data.Image;

                return this.assetService.assetsGetAssets({ ids: (d.data.Image && d.data.Image['iv'] &&d.data.Image['iv'].length > 0) ? d.data.Image['iv'].join(",") : "" , app: this.applicationConfig.appName }).pipe(map(e => {
                  const imageDtoItem = new ImageDto();
                  imageDtoItem.title = d.data.Title[this.languagueService.languague];
                  imageDtoItem.description = d.data.Description[this.languagueService.languague];
                  const imageUrl = this.assetUtilityService.getLinkFromAssetDto(e);
                  imageDtoItem.imageUrl = imageUrl && imageUrl.length > 0 ? imageUrl[0] : "";

                  return imageDtoItem;
                }), catchError(err => of(err)))

                forkJoin(listImageDtoObs).subscribe(f => {
                  item.images = f;
                  listResult.push(item);
                  obs.next(listResult);
                })


              })
            })
          }
        })
      })
    }

    return obs;
  }

Update 29/07/2022:

My solution


public getGalleryImagesContentDtoObservableById(id: string): Observable<ImageGalleryComponentDto>{

    if(id){
      const obs =  this.galleryImagesService.getGalleryImagesContent({id: id})
      .pipe(
        mergeMap((galleryImagesRes)=>{
          return this.galleryImageService.queryGalleryImageContent({ids: galleryImagesRes.data.Images['iv'].join(",")}).pipe(map(a => {
            return {
              galleryImagesRes: galleryImagesRes,
              galleryImageRes: a.items
            }
          }))
        }),
        mergeMap((galleryImageRes)=>{

          const imageAssetIds = galleryImageRes.galleryImageRes.map(b =>{
            return b.data.Image[this.languagueService.languague][0];
          });

          const listImageDtp =  imageAssetIds.map(c =>{
            return this.assetService.assetsGetAsset({id:c, app: this.applicationConfig.appName}).pipe(map(d =>{
              const imageDto = new ImageDto();
              imageDto.imageUrl = this.assetUtilityService.getLinkFromAssetDto(d);
              return imageDto;
            }))
          })

          return forkJoin(listImageDtp).pipe(map(e =>{
            return {
              galleryImagesRes: galleryImageRes.galleryImagesRes,
              galleryImageRes: galleryImageRes.galleryImageRes,
              imagesDto: e
            }
          }))


        }
        )
      ).pipe(map(finalRes =>{
        const imageGalleryComponentDto = new ImageGalleryComponentDto();
        imageGalleryComponentDto.id = finalRes.galleryImagesRes.id;
        imageGalleryComponentDto.title = finalRes.galleryImagesRes.data.Title[this.languagueService.languague];
        imageGalleryComponentDto.images = finalRes.imagesDto;
        return imageGalleryComponentDto;
      }));

      return obs;
    }

    return of();
  }
quanchinhong
  • 142
  • 3
  • 18
  • use combination operators in the order you need to avoid this kind of fat functions. Read here on combine latest and similar to help you refactor your code: https://www.learnrxjs.io/learn-rxjs/operators/combination/combinelatest – onrails Jul 28 '22 at 14:57

1 Answers1

0

Solution, using mergeMap and forkJoin

public getGalleryImagesContentDtoObservableById(id: string): Observable<ImageGalleryComponentDto>{

    if(id){
      const obs =  this.galleryImagesService.getGalleryImagesContent({id: id})
      .pipe(
        mergeMap((galleryImagesRes)=>{
          return this.galleryImageService.queryGalleryImageContent({ids: galleryImagesRes.data.Images['iv'].join(",")}).pipe(map(a => {
            return {
              galleryImagesRes: galleryImagesRes,
              galleryImageRes: a.items
            }
          }))
        }),
        mergeMap((galleryImageRes)=>{

          const imageAssetIds = galleryImageRes.galleryImageRes.map(b =>{
            return b.data.Image[this.languagueService.languague][0];
          });

          const listImageDtp =  imageAssetIds.map(c =>{
            return this.assetService.assetsGetAsset({id:c, app: this.applicationConfig.appName}).pipe(map(d =>{
              const imageDto = new ImageDto();
              imageDto.imageUrl = this.assetUtilityService.getLinkFromAssetDto(d);
              return imageDto;
            }))
          })

          return forkJoin(listImageDtp).pipe(map(e =>{
            return {
              galleryImagesRes: galleryImageRes.galleryImagesRes,
              galleryImageRes: galleryImageRes.galleryImageRes,
              imagesDto: e
            }
          }))


        }
        )
      ).pipe(map(finalRes =>{
        const imageGalleryComponentDto = new ImageGalleryComponentDto();
        imageGalleryComponentDto.id = finalRes.galleryImagesRes.id;
        imageGalleryComponentDto.title = finalRes.galleryImagesRes.data.Title[this.languagueService.languague];
        imageGalleryComponentDto.images = finalRes.imagesDto;
        return imageGalleryComponentDto;
      }));

      return obs;
    }

    return of();
  }
quanchinhong
  • 142
  • 3
  • 18