1

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()">
1
  • The better way for your scenario is using the rxjs debounce operator. Commented Mar 8, 2017 at 11:58

3 Answers 3

6

Why dont use debounceTime(500) instead of setTimeout.

https://www.learnrxjs.io/operators/filtering/debouncetime.html

Sign up to request clarification or add additional context in comments.

4 Comments

If you have an account in egghead this video is so helpfull for your case. egghead.io/courses/build-an-angular-2-instant-search-component
How would it look like in my case? I have posted html code with keyup event.
plnkr.co/edit/ycJKwFtmbcF5dupIHlOJ?p=preview It doesn't work correctly. Try to enter few chars quickly, it will fire the function without the delay.
Because you arent use debounce, You are use your function directly with keyup event, and dont use a debounce. Dont delete the term$ because here is where the debounce work plnkr.co/edit/3W7ZLtpaBL4Mo1nVvmJI
0

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);

Comments

0

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 );

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.