angularasynchronousresolver

Simple subscribe within the resolver in Angular 11. How to wait until subscribe is complete so I can do a comparison of data


This is different from other questions because I am trying to have the subscribe within the map() method.

I have started working with a resolver recently and still a little iffy in regards to how the async functionality works between the pipe and the subscribe.

I have a method getAssociatedPartners which will return an array of objects. [{partnerId:1},{partnerId:10}]. Within this method is a subscribe which will call the backend to get this data.

I also have a resolve method which makes another call to another db using getPartnerById, and gets one object {id:1, partnerId:10}.

Once the subscribe from getAssociatedPartners is complete, and data from getPartnerById is complete, I would like to see if partnerId in the array from getAssociatedPartners and this.partner.id has a match.
If so then I would like to continue and return the result as it is on the line --> return partner as Partner. If not then I will redirect.

How can I make the method this.getAssociatedPartners wait until the data is returned so that I can use var partnerIds to do comparisons with this.partner?

Currently it does not wait, and passes up the method and finishes the resolver before the data is returned. "here2" gets console.logged before the this.getAssociatedPartners has data returned.

      resolve(route: ActivatedRouteSnapshot): Observable<Partner> {
    return this.aService.getPartnerById(route.params['id']).pipe(
      map((partner) => {
        var partnerIds = this.getAssociatedPartners(route.params['seoUrl']);
        console.log("here2")
            this.partner = partner;
            if (this.partner === undefined) {
                this.router.navigate(['**']);
              } else {
                if (!this.partner.website.includes('http')) {
                  this.partner.website = 'https://' + this.partner.website;
                }
              }
          return partner as Partner;
      }),
      catchError(() => {
        this.router.navigate(['/error']);
        return EMPTY;
      })
    );
  }

  getAssociatedPartners(seoUrl:string) : object[]{
      console.log(seoUrl)
    this.VHService.getPartnerIds(seoUrl).subscribe((result) =>{
        this.partnerIds = result.data;
        console.log("here1")
    })
    return this.partnerIds;
  }

Solution

  • I think you can use forkJoin to combine the 2 observables and return the one you want. I dont have the same setup as you so you might need to modify this code.

    This should allow you to run both observables and compare their results.

    Let me know if this helps.

    
    resolve(route: ActivatedRouteSnapshot): Observable<Partner> {
    return forkJoin(
        // as of RxJS 6.5+ we can use a dictionary of sources
        {
          p1: this.aService.getPartnerById(route.params['id']),
          p2:  this.VHService.getPartnerIds(route.params['seoUrl'])
        }
      ).pipe(
        map((partners) => {
          /*  logic 
              Access both observables as like an map
              partners.p1
              partners.p2
          */
          return partners.p1 as Partners;
        }),
        catchError(() => {
          this.router.navigate(['/error']);
          return EMPTY;
        })
      );
    }