Как получить службу debounce при событии ввода keyup в angular2 с помощью rxjs
Я пытаюсь вызвать службу при вводе событий ввода.
HTML
<input placeholder="enter name" (keyup)='onKeyUp($event)'>
Ниже приведена функция onKeyUp()
onKeyUp(event) {
let observable = Observable.fromEvent(event.target, 'keyup')
.map(value => event.target.value)
.debounceTime(1000)
.distinctUntilChanged()
.flatMap((search) => {
// call the service
});
observable.subscribe((data) => {
// data
});
}
На вкладке "Сеть" браузера было обнаружено, что он вызывает функцию "key-up" в каждом событии с ключом (как это и предполагалось), но то, что я пытаюсь достичь, - это время отладки 1сек между каждым сервисным вызовом. Кроме того, событие срабатывает, если я перемещаю стрелку.
ссылка plunkr
Ответы
Ответ 1
Таким образом, цепочка действительно правильная, но проблема в том, что вы создаете Observable и подписываетесь на него при каждом событии keyup
. Вот почему он печатает одно и то же значение несколько раз. Есть просто несколько подписок, а это не то, что вы хотите сделать.
Очевидно, есть больше способов сделать это правильно, например:
@Component({
selector: 'my-app',
template: '
<div>
<input type="text" (keyup)='keyUp.next($event)'>
</div>
',
})
export class App implements OnDestroy {
public keyUp = new Subject<KeyboardEvent>();
private subscription: Subscription;
constructor() {
this.subscription = this.keyUp.pipe(
map(event => event.target.value),
debounceTime(1000),
distinctUntilChanged(),
mergeMap(search => of(search).pipe(
delay(500),
)),
).subscribe(console.log);
}
ngOnDestroy(): void {
this.subscription.unsubscribe();
}
}
Смотрите обновленную демоверсию: http://plnkr.co/edit/mAMlgycTcvrYf7509DOP
Январь 2019: обновлено для RxJS 6
Ответ 2
@marlin дал отличное решение, и оно отлично работает в angular 2.x, но с angular 6 они начали использовать версию rxjs 6.0, и у нее немного другой синтаксис, так что вот обновленное решение.
import {Component} from '@angular/core';
import {Observable, of, Subject} from 'rxjs';
import {debounceTime, delay, distinctUntilChanged, flatMap, map, tap} from 'rxjs/operators';
@Component({
selector: 'my-app',
template: '
<div>
<input type="text" (keyup)='keyUp.next($event)'>
</div>
',
})
export class AppComponent {
name: string;
public keyUp = new Subject<string>();
constructor() {
const subscription = this.keyUp.pipe(
map(event => event.target.value),
debounceTime(1000),
distinctUntilChanged(),
flatMap(search => of(search).pipe(delay(500)))
).subscribe(console.log);
}
}
Ответ 3
Я бы посоветовал вам проверить учебник Angular2, который показывает чистый и объясненный пример чего-то похожего на то, что вы просите.
https://angular.io/docs/ts/latest/tutorial/toh-pt6.html#!#observables
Ответ 4
Ну, вот базовый дебютант.
ngOnInit ( ) {
let inputBox = this.myInput.nativeElement;
let displayDiv = this.myDisplay.nativeElement;
let source = Rx.Observable.fromEvent ( inputBox, 'keyup' )
.map ( ( x ) => { return x.currentTarget.value; } )
.debounce ( ( x ) => { return Rx.Observable.timer ( 1000 ); } );
source.subscribe (
( x ) => { displayDiv.innerText = x; },
( err ) => { console.error ( 'Error: %s', err ) },
() => {} );
}
}
Если вы настроите два указанных дочерних представления (ввод и отображение), вы увидите, что работа над debounce. Не уверен, что это не делает ничего, что вы делаете, но эта базовая форма (насколько мне известно) является простым способом отладки, я использую эту начальную точку совсем немного, набор внутреннего текста - это всего лишь образец, он может сделать служебный вызов или что-то еще, что вам нужно для этого.