2
export class DropDownService {
    private dockerURL;
     constructor(private infoService: InfoService){
            this.infoService.getVersion().subscribe((URL) => {
                 this.dockerURL = URL;
             });
            // How to make sure the dockerURL is loaded
            // before getStructureType is invoked from other services
    }
   getStructureType(): Observable<StructureType[]> {
       return this.http.get<StructureType[]>(this.dockerURL+'/structureType');
    }
}

How to make sure dockerURL is loaded before getStructureType is invoked from other services?

sudheer
  • 145
  • 9

2 Answers2

1

You can take advantage of switchMap for this.

Something like this:

import { of } from 'rxjs';
import { tap } from 'rxjs/operators';
.....
export class DropDownService {
    private dockerURL;
     constructor(private infoService: InfoService){

     }

   getStructureType(): Observable<StructureType[]> {
       return this.getDockerURL().pipe(
          switchMap(url => {
             return this.http.get<StructureType[]>(url+'/structureType');
          }),
       );
    }

  private getDockerURL(): Observable<string> {
    if (this.dockerURL) {
      return of(this.dockerURL);
    } else {
      return this.infoService.getVersion().pipe(
       // tap is an operator that is used for side effects, every time this stream emits, we assign it to this.dockerURL. Should only be once.
       tap(url => this.dockerURL = url),
      );
    }
  }
}

This way, it ensures that dockerURL gets populated before making HTTP call.

AliF50
  • 16,947
  • 1
  • 21
  • 37
  • Thank you. However, I have many other functions like getStructureType, Do I have to add it in every function? is there another approach you can think of to load even before? – sudheer Mar 19 '20 at 20:18
  • https://stackoverflow.com/questions/41619443/how-to-call-an-rest-api-while-bootstrapping-angular-2-app You can make an API call upon bootstrapping but if that doesn't make sense in this situation, I am going to make an edit and drop a line here when it is done. – AliF50 Mar 19 '20 at 20:22
  • Assuming the URL is the same, I made it into a cache. It is up to you to experiment and maybe make it better for your situation. If a cache doesn't make sense, and you have to make API calls always, then I don't think there is an alternative to what I showed you first. In essence, you will always have to retrieve the URL from the server. – AliF50 Mar 19 '20 at 20:27
0

Subscribe comes with err and success function callbacks. You can call getStructureType in success callback. The success callback gets called only when the request is complete.

this.infoService.getVersion().subscribe((URL) => {
       //...
   },
    err => { //========> if fails this gets called
        console.log(err );
    }
    suc => { // =======> gets called on success when its successfully executed
       this.dockerURL = URL;
       this.http.get<StructureType[]>(this.dockerURL+'/structureType');
    }
);
Mr Khan
  • 2,139
  • 1
  • 7
  • 22
  • I am not the one who invokes getStructureType, it is invoked by other services in the application. I don't have control of it. – sudheer Mar 19 '20 at 20:19
  • You can use Resolver to solve this problem. The Resolver waits for the request to complete before the view is rendered. – Mr Khan Mar 19 '20 at 20:24