入力キーアップイベントでサービスを呼び出そうとしています。
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
});
}
_
ブラウザのネットワークタブから、すべてのキーアップイベントでキーアップ機能を呼び出していることがわかりました(想定どおり)が、私が達成しようとしているのは、各間の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年1月:RxJS 6用に更新
@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);
}
}
Angular2チュートリアルを確認することをお勧めします。このチュートリアルでは、あなたが求めているものに似た、わかりやすく説明された例を示しています。
https://angular.io/docs/ts/latest/tutorial/toh-pt6.html#!#observables
さて、ここに基本的なデバウンサーがあります。
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 ) },
() => {} );
}
}
示された2つのビューの子(入力とディスプレイ)を設定すると、デバウンスが機能することがわかります。これがあなたのすることを何もしないかどうかはわかりませんが、この基本的な形式は(私が知る限り)デバウンスするための簡単な方法です、私はこの出発点をかなり使用しますサービスコールなど、必要なことを行うことができます。