Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to cancel http request with switchMap?

I want to cancel the previous http request if i made the new http request to server but it is not working as expected to me.

i want to cancel the request if some value got changed in the function i mean if the value change the old request should cancel and new one should create for this i have done this

1) Created a subject - The thing that will be watched by the observable
public stringVar = new Subject<string>();

2) Create an observable to watch the subject and send out a stream of updates (You will subscribe to this to get the update stream)

public stringVar$ = this.stringVar.asObservable()

3)In a particular function i am getting the value as an argument so i perform these steps

  testFunction(value){
      this.stringVar.next(listValueSelected);
      this.testOutput = this.stringVar$.pipe(
             switchMap(() => {
                return  this.teseService.getEntries(val_one, val_two,val_three);
           })
         )
         this.testOutput.subscribe(result => console.log(`${result}`));
    } 

The request is cancelble when value is going to change but getting vary strange behaviour first time only one request is mode but when i click second time it calling api two time and this will go on .What is wrong with my code ?

in the component.ts

export class TestComponent {
    testOutput :Observable<any>;
    stringVar =  new Subject<number>();
    stringVar$ = this.stringVar.asObservable();

 testResult(selectedValue) {
       this.stringVar.next(selectedValue);
       this.stringVar$.subscribe(data => {
      });
       this.testOutput = this.stringVar$.pipe(
             switchMap(() => {
                return  this.testService.getTestEntries(this.x,this.y,this.z);
           })
         )
         this.testOutput.subscribe(result => console.log(`${result}`));
    }

}

in the service file

getTestEntries(x, y,selectedValue): Observable<any>{
        let apiUrl = selectedValue=='3'?this.baseUrl1:this.baseUrl ;

        return this.http.post(apiUrl,obj).map((response: Response) => {

              return response;
        })
      }

i want to cancel my old request and create new if the value "selectedValue" changed in the component.

like image 741
Ankit0827 Avatar asked Jul 09 '19 18:07

Ankit0827


People also ask

How do I cancel http request?

We can use the AbortController object and the associated AbortSignal with the Fetch API to make cancelable HTTP requests. Once the AbortSignal is sent, the HTTP request is canceled and won't be sent if the cancellation signal is sent before the HTTP request is done.

How do I cancel HttpClient request?

Using CancellationToken to Cancel Requests Sent with HttpClient. In the introduction, we stated that if a user navigates away from a page, they need the response no more, and thus it is a good practice to cancel that request.

What is switchMap RxJS?

RxJS switchMap() operator is a transformation operator that applies a project function on each source value of an Observable, which is later merged in the output Observable, and the value given is the most recent projected Observable.

What is the use of switchMap?

switchMap operator is basically a combination of two operators - switchAll and map. The map part lets you map a value from a higher-order source observable to an inner observable stream.


1 Answers

I believe that you call your method testResult(selectedValue) whenever you click the button, so this will create new Observable and subscribe to it as you click the button and call the method. These new Observable subscriptions are causing multiple network requests.

Ideally you want to subscribe to the stringVar$ only once in the constructor and when something changes just emit updated value in the stringVar Subject. Since Observable subscription is only one and already existing, it will catch emitted new value and will create new http request with the help of switchMap operator.

FYI you have correctly chosen switchMap operator. It will discard latest network call if new event arrives in the meantime.

This is your working example:

export class TestComponent {
  testOutput: Observable<any>;
  stringVar = new Subject<number>();
  stringVar$ = this.stringVar.asObservable();

  constructor() {
    this.testOutput = this.stringVar$.pipe(
      switchMap(() => {
        return this.testService.getTestEntries(this.x, this.y, this.z);
      }),
    );
    this.testOutput.subscribe((result) => console.log(`${result}`));
  }

  testResult(selectedValue) {
    this.stringVar.next(selectedValue);
  }
}
like image 122
Goga Koreli Avatar answered Nov 02 '22 22:11

Goga Koreli