Home > Back-end >  Observable that manages a "request running" variable
Observable that manages a "request running" variable

Time:09-10

In Angular, I'm currently writing a lot of Code repeatedly like this:

  • I have service classes that return an Observable<XYZ>, that are sending requests to my backend
  • In my components I want to make sure that a request is only running once at the same time. So if a request takes a bit longer and the user hits a button again and again it doesn't start a new request. So my component has some requestRunning variable and invoking the service then looks like this:
myFunction() {
  if (this.requestRunning) {
    return;
  }
  this.requestRunning = true;
  this.myService.callBackend().subscribe(
    success => {
      doSomething();
    },
    error => {
      this.requestRunning = false;
    },
    _ => { // complete
      this.requestRunning = false;
    }
  );
}

What I would prefer is something like an Observable which I can pass in the requestRunning variable, and that sets it to true if the Observable is subscribed to, and set to false if the Observable finishes (complete/error).

Does somebody know a cool and DRY solution for this?

CodePudding user response:

you can use exhaustMap operator, this way you won't even need to maintain a variable to keep track of state, here the demo

though you'll need to change the way you are adding the listener on your button:

  ngOnInit() {
    const btn = this.button.nativeElement;

    // this will produce outer observable
    fromEvent(btn, "click")
      .pipe(
        exhaustMap(() => {
          console.log("calling api...");
          // this will produce inner observable, so exhaustMap will wait for inner 
          // observable to complete, until then it any emissions from outer observables are going to be ignored.
          return this.appService.callApi();
        })
      )
      .subscribe({
        next: (apiResponse) => {
          console.log("api response recieved");
        }
      });
  }
  • Related