简体   繁体   English

Angular:如何使用Observable.timer()和switchMap来消除函数调用的反跳?

[英]Angular: How to debounce a function call with Observable.timer() and switchMap?

This is my method: 这是我的方法:

  filter(value) {    
    this.backendCall(value)    
  }

I would like to put a delay between backend calls so that my method does not get called on every keystroke with Observable.timer() and switchMap. 我想在后端调用之间放置一个延迟,以免在每次使用Observable.timer()和switchMap的击键时都调用我的方法。

As an example I have this code from an async validator that does precisely what I want : 举例来说,我从异步验证器获得了这段代码,该代码正是我想要的

export function createAsyncValidator(checkFn: (value: string) => Observable<Boolean>, errorMessage: string) {
    return (control: AbstractControl): Observable<ValidationErrors> => {
        return Observable.timer(500).switchMap(() => {
            return checkFn(control.value)
                .map(result => (result ? null : { [errorMessage]: true }));
        });
    }
}

... but I am struggling to apply it to my method . ...但是我正在努力将其应用于我的方法 This is what I have tried: 这是我尝试过的:

  filter(value) {
    Observable.timer(500).switchMap(() => {
      return Observable.of(value);
    }).subscribe(() => {
      console.log('filter', value);
      // this.backendCall(value)
    });
  }

The delay is indeed applied, but all values are logged . 确实会应用该延迟,但是会记录所有值 I was expecting the swithMap to unsubsribe those observables that arrive during the delay. 我期望swithMap取消订阅延迟期间到达的那些可观察对象。 What am I missing here ? 我在这里想念什么?

Use the debounceTime before subscribing to an observable. 订阅可观察对象之前,请使用debounceTime

In your filter function emit an event with the value and react in the subscription with added debounceTime. 在您的过滤器函数中,发出带有该值的事件,并在订阅中以添加的debounceTime做出反应。

filter(value: ValueType) {
    this.filterSubject.next(value);
}

ngOnInit() {
    this.filterSubject = new Subject<ValueType>();
    this.filterSubject.debounceTime(500).subscribe((value: ValueType) => {
        this.backendCall(value);
    });
}

First I think you just miss the return statement there : 首先,我认为您只是错过了return语句:

filter(value) {
    -->return<-- Observable.timer(500).switchMap(() => {
      return Observable.of(value);
    }).subscribe(() => {
      console.log('filter', value);
      // this.backendCall(value)
    });
  }

But i dont really understand the logic you are trying to put here. 但是我真的不明白您要在这里提出的逻辑。

EDIT after this comment : 编辑此评论后:

I would like the backend call to happen only when I am done typing (with a delay of a second for example). 我希望仅在完成输入后才进行后端调用(例如,延迟一秒钟)。 Throttle would send my first keystroke to the backend right away 油门会立即将我的第一个按键发送到后端

You could simply use the debounceTime operator to implements such behavior. 您可以简单地使用debounceTime运算符来实现这种行为。

doc here doc在这里

So if you source is an input you could use it that way : 因此,如果您的来源是输入,则可以通过以下方式使用它:

<myFormControl>.valueChanges.debounceTime(500).flatMap(value => {
    return this.backendCall(value);
}).subscribe();

This way, the backendCall will be called 500ms after you stop typing. 这样,在您停止键入后,将调用backendCall 500ms。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM