How to Cancel Ongoing Http Requests When There's a New Requests in Angular 6 With Rxjs 6

How to use RxJS to cancel previous HTTP Requests in an Angular Service

In this case, you can simply unsubscribe the previous call using unsubscribe method. switchMap is used when we have a higher-order observable.

Just unsubscribe the previous call before making the next one.

fetchCounts(filters?: any): void {
this.loaded = false;
this.apiCall && this.apiCall.unsunscribe(); // Unsubscribe here as well.
this.apiCall = this.api.getCounts(filters).subscribe((results: any) => {
// do something with the returned data
this.loaded = true;
this.apiCall.unsunscribe();
});
}

How to cancel http request in Angular 6?

Long story short:

Easiest way to handle such situations is by using the switchMap operator. What this does is cancel the internal subscription as soon as a new event comes along.

One implementation would be:

class MainComponent {
products: any[];
private _filters$ = new Subject();

constructor(private dataService: DataService_, private filtersService: FiltersService) {

}

ngOnInit() {
this.setProducts()
}

setProducts() {
this._filters$
.switchMap((filters)=> this.dataService.getProducts(filters)) // or .let(switchMap...) if you are using rxjs >5.5
.subscribe(products => this.products = products);
}

onFiltersChange() {
this._filters$.next(this.filtersService.filters);
}
}

Long story:

What happens here is:
When you change filter the onFilterChange is triggered. You then emit the latest filters (inside this.filtersService.filters) through the _filters$ Subject (a subject is almost identical to an EventEmitter).

Back in time during component initialization the ngOnInit method has called setProducts, which has subscribed to the _filters$ subject for future events (none has happened at this point). When an event arrives on _filters$ then we trigger the getProducts method of dataservice, passing it the filters that where contained in the event. We will be waiting on this line until the http call has completed. As soon as it completes the result of the http call will be assigned to the products of the component.

If while we are waiting for the http response to get back, onFiltersChange is fired again, then a new event will arive at the switchMap and it will cancel the previous http request so that it can handle the new event.

This is a very powerful approach as changing a single operator, you can easily change the behavior of your app. For instance, changing switchMap to concatMap will make the request wait for the previous one to complete (will happen serially). Changing it to flatMap will have the same behaviour as the original code you posted (http requests will happen as soon as filters change, without affecting previous ones, order of responses will not predictable) and so on.

Observables : Cancel previous http request on new subscription call

I would use a subject to keep everything reactive. In your template html listen to change events and emit a new value to the subject.

 <searchBar (change)="search$.next($event.target.value)" />

then in your component:

  this.subscription = this.search$.pipe(
debounceTime(800),
distinctUntilChanged(),
switchMap(searchText=>http.post('api_link', {searchText})
}).subscribe(response=>{
this.response = response.
});

The switchMap will cancel any HTTP request that hasn't completed if a new value is emitted through the subject. You can play with the debouneTime to see what feels right for you. Lastly, make sure you unsubscribe from your subject in the ngOnDestroy, this will prevent any memory links and keep everything nice and perfromant.:

ngOnDestroy(){
this.subscription.unsubscribe();
}

Suresh's answer has a distinctUntilChanged() which is an excellent addition to the solution. I'm adding it but want to give credit to his answer below. This is a benefit because if I search for egg the request is made. But then I add an s the end of egg and change my mind before the debounce is completed another duplicate HTTP post with a search of egg will not be made.

RxJS cancellable HTTP queue

Assuming you have some kind of id in the item, you could do something like this.

queue.pipe(
groupBy((item) => item.id), // split queue values into independent obs based on grouping key
mergeMap( // process each group obs in parallel
(group$) => group$.pipe(
switchMap((item) => this.httpClient.get(item)) //cancel prev req in the group if still running
)
)
)
.subscribe(console.log);

cheers

Cancelling ongoing Angular $http requests when there's a new request

The solution is to set up the promise, then with each search() cancel it and reinitialize a new one. This will reliably cancel any previous $http():

var canceler = $q.defer();

$scope.search = function() {

canceler.resolve();

canceler = $q.defer();

$http({
method: "GET",
url: "/endpoint.php"
params: {
query: $scope.query
}
timeout: canceler.promise
}).then(function(response) {
$scope.results = response.data;
})
}

RxJS 6 - Angular 6 - Properly canceling current http request if a new one is triggered

Your code is describing the process of sending an http request each time your OnClientUpdate observable yields. Each yield ends up selecting an observable which represents an http request. switchMap will subscribe to that http request observable and dispose of it's subscription to any prior http request observable. If that observable's subscription properly implements the disposal of the http request, switchMap will work as intended.

However, depending on how often OnClientUpdate can yield, you may want to add a debounce operation, thus preventing rapid-fire http request and cancellations.

Example - don't spam, cancel all but the latest request, and yield each latest result:

var latestHttpRequestResult =
trigger
.pipe(debounce(200))
.pipe(switchMap(sendHttpRequestAsObservable));


Related Topics



Leave a reply



Submit