订阅FormBuilder valueChanges时,使用debounceTime和distinctUntilChanged不起作用

时间:2019-04-10 09:30:23

标签: angular rxjs angular-reactive-forms

非常简单地说,我想在用户停止输入设置的时间后执行查询。我所见过的使用FormBuilder的每一篇教程都建议在管道valueChangesdebounceTime的同时订阅输入字段的distinctUntilChanged

this.threadForm.get('body').valueChanges.pipe(
            debounceTime(500),
            distinctUntilChanged(),
            mergeMap(search => this.db.query$(...)`))
      )

我无法使它正常工作。它似乎可以正确地消除时间的抖动,但是当它通过管道传输时,它会发送多个最终结果(distinctUntilChanged应该处理)。我在做什么错了?

以下是该问题的快速视频(我添加了tap,因此您可以看到该网页记录了一些最终结果):

https://streamable.com/h2him

谢谢!

编辑:添加周围的代码 source函数也在每次按键单击时运行,因此我认为无论实例如何弹跳,我都实例化了多个可观察对象。如何在其中添加去抖逻辑?

  source: (searchTerm, renderList) => {
    //searchTerm is triggered on every button click
    if (searchTerm.length === 0) {
      renderList(this.mentions, searchTerm)
    } else {
      //are multiple instances of this observable being made??
      this.threadForm.get('body').valueChanges.pipe(
        distinctUntilChanged(),
        debounceTime(500),
        tap(x => console.log(x)),
        switchMap(search => this.db.query$(`user/collection?like=username_${searchTerm}&limit=5`))
      ).subscribe( x => {
        console.log(x)
      });
    }
  },

2 个答案:

答案 0 :(得分:1)

我非常确定这里的问题与valueChanges发出的对象有关。由于distinctUntilChanged发出的对象是不同的,您可能需要首先将此对象映射到实际需要的值。 (您还可以向distinctUntilChanged发送回调,以控制不同的内容)

例如

this.threadForm.get('body').valueChanges.pipe(
  debounceTime(500),
  map( (obj) => obj.searchVal ),
  distinctUntilChanged(),
  mergeMap(search => this.db.query$(...)`))
)

您肯定会在switchMap上寻找mergeMap

编辑

要使用源功能,您可以像这样使用Subject。

var searchSubject = new Subject<any>();

source: (searchTerm, renderList) => {
  searchSubject.next({searchTerm, renderList});
}

除此searchSubject之外,您仅在ngOnInit中订阅一次,并在onDestroy函数中退订。

searchSubject.pipe(
 debounceTime(500),
 distinctUntilChanged(),
 mergeMap(search => this.db.query$(...)`))
)

答案 1 :(得分:0)

尝试一下:

this.threadForm.get('body').valueChanges.pipe(
  debounceTime(1000), 
  distinctUntilChanged()).subscribe(changes => {
  this.db.query$(...)
});