it-swarm.com.de

So erreichen Sie einen Debounce-Service für das Eingabe-Keyup-Ereignis in angle2 mit rxjs

Ich versuche, einen Dienst bei einem Eingabeschlüsselereignis anzurufen.

Das HTML

<input placeholder="enter name" (keyup)='onKeyUp($event)'>

Unten sehen Sie die Funktion 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
    });
}

Auf der Registerkarte "Netzwerk" des Browsers wurde festgestellt, dass die Key-Up-Funktion bei jedem Key-Up-Ereignis aufgerufen wird (wie es beabsichtigt ist). Ich versuche jedoch, eine Entprellzeit von 1 Sekunde zwischen den einzelnen Browsern zu erreichen Service-Anruf. Das Ereignis wird auch ausgelöst, wenn ich die Pfeiltasten verschieben. 

plunkr link

22
varun

Die Kette ist also wirklich korrekt, aber das Problem ist, dass Sie ein Observable erstellen und es bei jedem keyup-Ereignis abonnieren. Deshalb wird derselbe Wert mehrmals gedruckt. Es gibt einfach mehrere Abonnements, die Sie nicht möchten.

Es gibt natürlich mehr Möglichkeiten, dies richtig zu machen, zum Beispiel: 

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

Sehen Sie sich Ihre aktualisierte Demo an: http://plnkr.co/edit/mAMlgycTcvrYf7509DOP

Jan 2019: Aktualisiert für RxJS 6

43
martin

@marlin hat eine großartige Lösung gegeben und es funktioniert einwandfrei in eckigen 2.x, aber mit eckiger 6 haben sie angefangen, die Version rxjs 6.0 zu verwenden.

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

Ich würde vorschlagen, dass Sie das Angular2-Tutorial durchsehen, in dem ein sauberes und erklärtes Beispiel von etwas ähnlichem dargestellt wird, was Sie fragen.

https://angular.io/docs/ts/latest/tutorial/toh-pt6.html#!#observables

3
Simon Dufour

Nun, hier ist ein einfacher Debouncer. 

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 ) },
            () => {} );
    }
}

Wenn Sie die beiden angegebenen Ansichtskinder (Eingabe und Anzeige) einrichten, wird die Entprellungsarbeit angezeigt. Ich bin mir nicht sicher, ob dies nichts tut, aber diese grundlegende Form ist (soweit ich weiß) der unkomplizierte Weg zum Entprellen. Ich benutze diesen Ausgangspunkt ziemlich viel. Der innere Text ist nur ein Beispiel. Sie können einen Serviceanruf tätigen oder was Sie sonst noch benötigen. 

0
Tim Consolazio