0

I have two buttons

<button (click)="httpOne()">Btn 1</button>
<button (click)="httpTwo()">Btn 2</button>

clicking on the buttons i am triggering a http request. When i click on Btn 1 the http requests needs 10 seconds to be resolved. When i click on Btn 2 the http requests needs 4 seconds to be resolved.

httpOne() {
  this.http.get('some-url-1').subscribe(response => {
  });
}


httpTwo() {
  this.http.get('some-url-2').subscribe(response => {
  });
}

So i first click on button 1, then i click on button 2. I need to wait for the http call from Btn 1 when i click on button 2.

And when the http call is done on Button 1, then i need to start the call on Btn 2.

I know that i can disable the button, but people the client does not want that.I need solution for this because i am struggling with this.

11
  • I just sumulated this with buttons. I don't need to disable the buttons. I need to resolve this problem - wait for the http call as desribed here Commented Aug 30, 2021 at 12:34
  • Can you leave just a single button which will do all the logic (req1, wait, req2) ? Commented Aug 30, 2021 at 12:37
  • No, i nede to do this on this way.... Commented Aug 30, 2021 at 12:39
  • Does the inverse also need to be supported? If the user clicks Button 2, then Button 1, the client must wait for httpTwo() to complete before invoking httpOne()? Commented Aug 30, 2021 at 12:46
  • No Joshua. I don't need that requirement Commented Aug 30, 2021 at 12:56

3 Answers 3

1

You can achieve that by assigning the first request to Observable then wait for this Observable to emit a value in the second button method like the following:

obs1$: Observable<any>;
httpOne() {
    this.obs1$ = this.http.get('some-url-1');
    this.obs1$.subscribe((response) => {
        // do something here with response
    });
}

httpTwo() {
    // if the obs1$ has a value, then it will wait it to emit a value, then switch to the second request,
    // otherwise, it will switch to the second request directly.
    (this.obs1$ || of(true)).pipe(switchMapTo(this.http.get('some-url-2'))).subscribe((response) => {
        // do something here with second respone
    });
}
Sign up to request clarification or add additional context in comments.

4 Comments

my mistakr.It works - can you just please explain why we use of(true) here ?
As I commented in the answer, the of(true) is used to emit a value directly to be switched to the second request, you can use null or {} within the of, it's doesn't matter.
is there abt other way with which we can prevent duplicate http calls - so http call 1 to be triggered just once in the httpTwo call - in each btn 2 call ?
Do you mean, you need to call both HTTP requests using the same button?
0

You can either do something like this:

class YourComponent {
  btn2Disabled = true;

  httpOne() {
   this.http.get('url1').subscribe({ next: res => this.btn2Disabled = false });
  }
  httpTwo() {
    this.http.get('url2').subscribe(/*...*/);
}

This disables the second button until the first request has returned something but does not trigger the second request.

Or you could do something like this with only one button:

httpOne() {
  return this.http.get('url1');
}

httpTwo() {
  return this.http.get('url2');
}
sequenceRequests() {
  this.httpOne().pipe(
    map(res => /** Do something with the result */),
    switchMap(() => this.httpTwo()),
  ).subscribe({ next: res => /** Do something with the result of the second call */})
}

You can even declare what to do with each result inside the relevant method and just call the first one, switchmap the second, subscribe.

Comments

0

I'm assuming you want this wait to work both ways, regardless of what button is clicked first. We can use a Subject to emit a queue of HTTP requests, and set it up in a way that only one request can be active at a time.

Here's the TypeScript

private httpOne() {
  return this.http.get('some-url-1').pipe(
    map(response=>{})
  );
}

private httpTwo() {
  return this.http.get('some-url-2').pipe(
    map(response=>{})
  );
}

private httpType = new Subject<1 | 2>();

private httpQueueSub = this.httpType.pipe(
  concatMap(type => type === 1 ? this.httpOne() : this.httpTwo()))
).subscribe();

public httpCall(type:1|2){
  this.httpType.next(type);
}

Then in your HTML

<button (click)="httpCall(1)">Btn 1</button>
<button (click)="httpCall(2)">Btn 2</button>

Notice that I've changed httpOne() and httpTwo() to run its response logic inside a map() operator instead of subscribe(). This allows us to declare two observables that can be subscribed to at a later time.

Next we setup a Subject that emits the type of HTTP request we need to make. We then create a single subscription that listens to that subject, and subscribes to either observable based on the Subject's emitted value.

The key operator here is concatMap() which does two important things.

  1. Creates a queue for the HTTP subscription.
  2. Ensures the next item in queue can't start a new HTTP request until the current one is complete.

Now in our HTML, we just need to invoke the function that makes our Subject emit the next HTTP request type.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.