Reputation: 7
switchMap doesn't cancel previous http request. Also tried with exhaustMap but didn't help. here's gist for the same https://gist.github.com/saiumesh-letznav/a33ac54444ba707b9dbb172271b518fe
import { Subject } from 'rxjs';
import { switchMap } from 'rxjs/operators';
import Axios from 'axios';
const baseUrl =
'https://api.github.com/search/repositories?q=golang+language:go&sort=stars&order=desc';
class GitService {
private $obs: Subject<void> = new Subject();
constructor() {
this.$obs
.pipe(switchMap((_) => Axios.get(baseUrl)))
// tslint:disable-next-line:no-console
.subscribe((res) => console.log({ res }));
}
public getGOlangRepos() {
this.$obs.next();
}
}
const instance = new GitService();
instance.getGOlangRepos();
instance.getGOlangRepos();
instance.getGOlangRepos();
instance.getGOlangRepos();
Upvotes: 1
Views: 2433
Reputation: 84982
If you want to actually cancel the axios request (rather than letting it continue but ignoring its result), then you can't simply switchmap to the promise returned by axios.get. Promises aren't cancellable, and while axios does support cancellation, rxjs has no idea how axios's cancellation works. So you'd need to implement the cancellation yourself.
Outside of rxjs, here's how you can make an axios request and then cancel it later:
const cancelToken = Axios.CancelToken.source();
const promise = Axios.get(someUrl, { cancelToken: cancelToken.token };
// ... then later to cancel it:
cancelToken.cancel();
If you want rxjs to be able to use this cancellation logic , you'll need to create a custom observable. If this is something you think you'll be doing often, i'd recommend moving it into a helper function. Something like this:
function getAsObservable(url) {
return Observable.create(function(observer) {
const cancelToken = Axios.CancelToken.source();
Axios.get(url, { cancelToken: cancelToken.token })
.then(result => {
observer.next(result);
observer.complete();
}, err => {
if (axios.isCancel(err)) {
observer.complete();
} else {
observer.error(err);
}
})
return () => cancelToken.cancel();
});
}
And then your code can become:
this.$obs
.pipe(switchMap((_) => getAsObservable(baseUrl)))
.subscribe((res) => console.log({ res }));
Upvotes: 8
Reputation: 18762
You can avoid multiple http calls by using debounceTime so that you add a delay before making http call. Once an http call is made, it will continue to be processed by server even if the subscription is cancelled in client app.
For example - below code will wait for 500ms before making http call.
constructor() {
this.$obs
.pipe(
debounceTime(500),
switchMap((_) => Axios.get(baseUrl))
)
// tslint:disable-next-line:no-console
.subscribe((res) => console.log({ res }));
}
Upvotes: -1