Michael
Michael

Reputation: 13616

How to execute function one after another?

I use angular 10 in my project. I have two functions initData1 and initData2.

I have two functions:

initData1(){
    //some http client services

    this.dataService.getTitleImageUrl(this.data.titlId, this.data.id )
    .subscribe( resp => {  this.titeImageUrl = encodeURI(resp.results[0]) });

    this.storeService.getContactImageUrl(this.store.titlId, this.store.id )
    .subscribe( resp => {  this.contactImageUrl = encodeURI(resp.results[0]) });
}


initData2(){
   //some http client services

    this.dataService.getTitleImageUrl(this.data.titlId, this.data.id )
    .subscribe( resp => {  this.titeImageUrl = encodeURI(resp.results[0]) });

    this.storeService.getContactImageUrl(this.store.titlId, this.store.id )
    .subscribe( resp => {  this.contactImageUrl = encodeURI(resp.results[0]) });
}

Here how I call functions in my component:

      ngOnInit(): void  {
        initData1();
        initData2();
      }
      

My question is how to execute the initData2 function only after all httpclient services are resolved in the initData1 function?

UPDATE: add examples of http client services

Upvotes: 2

Views: 3083

Answers (2)

Barremian
Barremian

Reputation: 31105

Ideally you'd have to use some of the RxJS functions and operators at your disposal. And when it comes to observables,

  1. It's better to subscribe them where it's response is required
  2. Use as less subscriptions as possible

Given these, I'd make the following changes to your implementation.

initData1(): Observable<any> {  // <-- return observable here
  // use `forkJoin` function to trigger multiple observables in parallel
  return forkJoin({
    title: this.dataService.getTitleImageUrl(this.data.titlId, this.data.id),
    contact: this.dataService.getTitleImageUrl(this.data.titlId, this.data.id)
  }).pipe(
    // use `tap` operator to perform side-effects
    tap(imageUrls => {
      this.titleImageUrl = encodeURI(imageUrls.title.results[0]);
      this.contactImageUrl = encodeURI(imageUrls.contact.results[0]);
    })
  );
}

initData2(): Observable<any> {  // <-- return observable here
  // use `forkJoin` function to trigger multiple observables in parallel
  return forkJoin({
    title: this.dataService.getTitleImageUrl(this.data.titlId, this.data.id),
    contact: this.dataService.getTitleImageUrl(this.data.titlId, this.data.id)
  }).pipe(
    // use `tap` operator to perform side-effects
    tap(imageUrls => {
      this.titleImageUrl = encodeURI(imageUrls.title.results[0]);
      this.contactImageUrl = encodeURI(imageUrls.contact.results[0]);
    })
  );
}

And later you could use higher order mapping operator (for co-dependent) observables to map from one observable to another

ngOnInit() {
  this.initData1().pipe(
    switchMap(imageUrls => this.initData2())
  ).subscribe(
    response => { 
      // response from `this.initData2()`
    },
    error => {
      // handle errors
    }
  );
}

Further information on handling nested subscriptions here.

Upvotes: 2

Tushar
Tushar

Reputation: 2078

You can simply call the second function initData2(); inside the response block of first function call.

initData1(){
    this.httpClient.get(yourURL).subscribe(response => {
        initData2();
    })
}

In this way it will call one after another.

Upvotes: 1

Related Questions