Reputation: 13
I have a http request which is being fired if user enters at least 4 characters inside the input and fires everytime he changes it's content (adding/removing letters). I want to add a timeout, that if user starts typing characters, the function will wait 1 second until it fires the request, to avoid a lot of requests when user is typing quickly. My attempt:
if (this.pointName.length >= 3) {
let timer = function() {
this.http.get(`./points.json`)
.subscribe(res => {
this.pointsArray = res.json();
});
};
clearTimeout(timer);
setTimeout(timer,1000);
My idea was to clear the timeout on every keyup
event and set it once again.
But unfortunately it gives me an error, that `Argument of type '() => void' is not assignable to parameter of type 'number'.
Is there any way to do it more efficientely? Maybe using RxJS? Anyways, I'm looking for a working solution. Thank you in advance.
HTML
<input type="text" id="searchInput" placeholder="Point name"(keyup)="getPoints()">
Upvotes: 1
Views: 8706
Reputation: 14564
Try this:
Create an RxJS Subject as a new member variable of your component
searchTerm$ = new Subject<string>();
In your component's ngOnInit method, set up your observable,
ngOnInit() {
this.searchTerm$
.filter( value => value.length >= 3)
.debounceTime(1000)
.switchMap( val => {
return this.http.get('./points.json')
.map(result => result.json());
})
.subscribe(result => .... // do what you want with the response );
}
In your HTML, change your keyup event binding to submit your input field's value
<input type="text" id="searchInput" placeholder="Point name"(keyup)="getPoints(this.value)">
Then in your component's getPoints method,send a value into your subject$
getPoints(value) {
this.subject$.next(value);
}
Basically, the observable you're creating does several things:
searchTerm$
.filter( value => value.length >= 3) // 1 filter out search terms that are shorter than 3 characters
.debounceTime(1000) // 2. only send events after no event comes for 1 sec
.switchMap( val => { // 3. convert your value to the result of your http request
return this.http.get('./points.json')
.map(result => result.json());
})
.subscribe(result => .... // do what you want with the response );
Upvotes: 0
Reputation: 445
First of all, you'd better use Debounce
operator in RxJS.
And the problem in your code is that you should pass the timer_id
into clearTimeout
instead of the function.
if (this.pointName.length >= 3) {
let timer = function() {
this.http.get(`./points.json`)
.subscribe(res => {
this.pointsArray = res.json();
});
};
let timer_id = undefined;
clearTimeout(timer_id);
timer_id = setTimeout(timer,1000);
Upvotes: 0
Reputation: 377
Why dont use debounceTime(500) instead of setTimeout.
https://www.learnrxjs.io/operators/filtering/debouncetime.html
Upvotes: 6