2

I have a function on my service called processPayment, this function gets the payment details and doing several http calls, transactional stuff and validations. The function is called from a component. What I couldn't find is, i dont want this function to handle any requests if its still running, lets say the user double clicks or something i want the function to ignore new requests while its running untill completion. Is this possible? Should i use a service function or a hot subject observable on the service? Maybe use exahustmap? Whats the best design pattern for that? Thanks!

TomerMiz
  • 377
  • 1
  • 3
  • 13
  • You're going to want to disable whatever triggers the function, so that the user cannot possibly click it again until the request is completed. You can use a simple boolean in your component to achieve that. –  May 28 '20 at 06:13
  • Could you provide more context? e.g: how/when is `processPayment` called from the component; do you need the results from `processPayment`? – Andrei Gătej May 28 '20 at 07:26

2 Answers2

0

lets say you have a component

public isCalled = false;

//Your Method where you call API

public callAPI() {
    if(this.isCalled) {
           return;
    }
    this.isCalled = true;
    this.http.get('url').subscribe(()=>this.isCalled=false;);
}

Note :- With Rxjs you will not be able to achieve it..because all the skip operators and other operators work works on continues subscription whose subscription stays alive even after first emit. In your case you are calling a api. It's subscription gets complete for that call and there is no next call in original observable source. each time you click you are making a new subscription.

Aakash Garg
  • 10,649
  • 2
  • 7
  • 25
  • Thanks guys, but this is the "old fashioned" way, is there any rxjs way? – TomerMiz May 28 '20 at 06:40
  • you only want to prevent a double click? – Aakash Garg May 28 '20 at 07:20
  • Thanks guys, please take a look at the solution with rxjs i described here: https://stackoverflow.com/questions/61867393/observable-stops-firing-even-when-catching-the-error please let me know if that works, its using exahustmap and subject to make sure the handleSeatClick will only handle one request at a time, i dont want to invent the wheel here so is this acceptable way to achieve it? – TomerMiz May 28 '20 at 07:51
  • in this so,lution you are using you will be having a continous subscription to that subject i believe. please unsubscribe to it in destroy. – Aakash Garg May 28 '20 at 07:56
  • Yes the subject is always subscribed, since the service in singleton i dont think i ever need to unsubscribe,but what do you think about the overall approach? I am new to angular and rxjs.. – TomerMiz May 28 '20 at 08:03
  • you should unsubscribe in ondestroy of your component. else in future it may lead to memory leaks. in your question above i believed you just wanted to hold a normal http call. I would still say in your case my answer is a simple a better apporach. no continuous observables required. Still you better know what you want to implement exactly. – Aakash Garg May 28 '20 at 08:05
0

you need to use exhaustMap, it will ignore the things, until the child stream has been completed.

process = new Subject();

constructor() {
  this.process.pipe(
    // unless the request isn't finished all emits of this.process will be ignored.
    exhaustMap(() => this.http.post()),

    // takeUntil(this.destroy$), // unsubscribe
  ).subscribe(response => {
    // some logic.
  });
}

processPayment() {
  this.process.next();
}
satanTime
  • 12,631
  • 1
  • 25
  • 73