0

Using Angular and the RxJS library.

I have a simple method:

method(){
 const data = this.data;
 const moreData = this.moreData;

 this.anotherMethodOne(data)
 this.anotherMethodTwo(moreData)
}

As you can see I am calling two other methods. anotherMethodOne() should be executed before anotherMethodTwo() - and it is.

Within anotherMethodOne() I have a .subscribe:

anotherMethodOne(data) {
 <!-- at this point it jumps out of this method and continues to proceed in the parent method, but returns later -->
 this.service.getService(id).subscribe(res => {
 res
 }
}

As soon as my debugger hits the .subscribe call it jumps back into the parent method() and proceeds to execute this.anotherMethodTwo(moreData). It then jumps back into this.anotherMethodOne(data) to finally complete the .subscribe - however, by this time its too late.

I need to make sure this.anotherMethodOne(data) is completed fully before this.anotherMethodTwo(moreData) runs or ensure that the .subscribe runs before it proceeds any further.

I started looking at switchMap and concat in the RxJS library, but unsure how that would be implemented in my case.

Tom Rudge
  • 3,188
  • 8
  • 52
  • 94
  • You don't want to subscribe that observable inside your anotherMethodOne. Instead return the observable to your caller and subscribe there. Inside that subscribe you can call the second method. – MikeOne Jan 27 '22 at 13:14

2 Answers2

2

You cannot guarantee an observable would've emitted before proceeding with it's emitted value. So you need to return the observable from the methods and subscribe where it's value is required.

For observable depending on the emissions of other observables, you could use higher order mapping operator like switchMap. More info about them here.

method(){
  const data = this.data;
  const moreData = this.moreData;

  this.anotherMethodOne(data).pipe(
    switchMap((someValue) => 
      this.anotherMethodTwo(moreData)
    )
  ).subscribe({
    // callbacks
  });
}

anotherMethodOne(data): Observable<any> {
  return this.http.get('url');
}

anotherMethodTwo(moreData): Observable<any> {
  return this.http.get('url');
}
ruth
  • 29,535
  • 4
  • 30
  • 57
0

When it comes to asynchronous functions, you should stay with the reactive approach and not try to determine when a certain code has finished, but instead just wait for it to finish and then invoke the callback or the responsible handler subsequently. Think about this. What is the subscribe never returns anything - is that okay? What if it takes a really long time to return anything - is that okay too?

But to fix the problem at hand, simply move anotherMethodTwo into the subscription. Then when something is returned, anotherMethodTwo is run.

method(){
 const data = this.data;
 const moreData = this.moreData;

 this.anotherMethodOne(data)
}

anotherMethodOne(data) {
 this.service.getService(id).subscribe(res => {
 console.log(res)
 this.anotherMethodTwo(moreData)
 }
}

Going down this path would be similar to async callback hell which nesting style is not recommended but it will do for now.

Joosep Parts
  • 5,372
  • 2
  • 8
  • 33