Сброс тайм-аута при каждом вызове функции Angular2 RxJS

У меня есть запрос http, который запускается, если пользователь вводит по крайней мере 4 символа во входе и срабатывает каждый раз, когда он меняет свой контент (добавление / удаление букв). Я хочу добавить тайм-аут, что если пользователь начинает вводить символы, функция будет ждать 1 секунду, пока не сработает запрос, чтобы избежать большого количества запросов, когда пользователь печатает быстро. Моя попытка:

if (this.pointName.length >= 3) {
  let timer = function() {
    this.http.get(`./points.json`)
        .subscribe(res => {
            this.pointsArray = res.json();
        });
    };
clearTimeout(timer); 
setTimeout(timer,1000);

Моя идея состояла в том, чтобы очистить тайм-аут на каждом keyup событие и установить его еще раз. Но, к сожалению, это дает мне ошибку, что `Аргумент типа '() => void' не может быть назначен параметру типа 'номер'.

Есть ли способ сделать это более эффективно? Может быть, используя RxJS? В любом случае, я ищу рабочее решение. Заранее спасибо.

HTML

 <input type="text" id="searchInput" placeholder="Point name"(keyup)="getPoints()">

3 ответа

Решение

Почему бы не использовать debounceTime(500) вместо setTimeout.

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

Прежде всего, вам лучше использовать Debounce оператор в RxJS. И проблема в вашем коде в том, что вы должны передать timer_id в clearTimeout вместо функции.

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

Попробуй это:

Создайте тему RxJS как новую переменную-член вашего компонента

searchTerm$ = new Subject<string>();

В методе ngOnInit вашего компонента, установите ваш наблюдаемый,

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

В своем HTML измените привязку события keyup, чтобы передать значение поля ввода

 <input type="text" id="searchInput" placeholder="Point name"(keyup)="getPoints(this.value)">

Затем в методе getPoints вашего компонента отправьте значение в ваш объект $

getPoints(value) {
  this.subject$.next(value);
}

По сути, наблюдаемая вами вещь делает несколько вещей:

 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 );
Другие вопросы по тегам