javascript - rxjs debouncetime
Cómo lograr un servicio de rebote en el evento keyup de entrada en angular2 con rxjs (4)
Estoy tratando de llamar a un servicio en el evento de entrada de clave de entrada.
El HTML
<input placeholder="enter name" (keyup)=''onKeyUp($event)''>
A continuación se muestra la función 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
});
}
Se encontró en la pestaña de red del navegador que está activando la función de creación de teclas en cada evento de activación de teclas (como se supone que debe hacer), pero lo que estoy tratando de lograr es un tiempo de rebote de 1 segundo entre cada una. llamada de servicio. Además, el evento se activa si muevo la tecla de flecha mover.
@marlin ha dado una gran solución y funciona bien en angular 2.x, pero con angular 6 han comenzado a usar la versión rxjs 6.0 y tiene una sintaxis ligeramente diferente, así que aquí está la solución actualizada.
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);
}
}
Bueno, aquí hay un debouncer básico.
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 ) },
() => {} );
}
}
Si configura los dos elementos de vista indicados (la entrada y la pantalla), verá el trabajo de rebote. No estoy seguro de si esto no hace nada de lo que usted hace, pero esta forma básica es (por lo que sé) la forma sencilla de rebatir, uso este punto de partida bastante, el conjunto del texto interno es solo una muestra, Podría hacer una llamada de servicio o cualquier otra cosa que necesite hacer.
Entonces, la cadena es realmente correcta, pero el problema es que estás creando el Observable y te suscribes a él en cada evento de keyup
. Es por eso que imprime el mismo valor varias veces. Simplemente hay varias suscripciones que no es lo que quieres hacer.
Obviamente hay más formas de hacerlo correctamente, por ejemplo:
@Component({
selector: ''my-app'',
template: `
<div>
<input type="text" (keyup)=''keyUp.next($event)''>
</div>
`,
})
export class App {
name:string;
public keyUp = new Subject<string>();
constructor() {
const subscription = this.keyUp
.map(event => event.target.value)
.debounceTime(1000)
.distinctUntilChanged()
.flatMap(search => Observable.of(search).delay(500))
.subscribe(console.log);
}
}
Vea su demostración actualizada: http://plnkr.co/edit/mAMlgycTcvrYf7509DOP
Le sugiero que consulte el Tutorial de Angular2 que muestra un ejemplo claro y explicado de algo similar a lo que está preguntando.
https://angular.io/docs/ts/latest/tutorial/toh-pt6.html#!#observables