使用 debounceTime &订阅 FormBuilder valueChanges 时 distinctUntilChanged 不起作用 [英] Using debounceTime & distinctUntilChanged is not working when subscribing to FormBuilder valueChanges

查看:19
本文介绍了使用 debounceTime &订阅 FormBuilder valueChanges 时 distinctUntilChanged 不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

简单地说,我想在用户停止输入一段时间后执行查询.我见过的每个使用 FormBuilder 的教程都建议订阅输入字段的 valueChanges,同时管道 debounceTimedistinctUntilChanged.

very simply put, I want to perform a query after the user stops typing for a set amount of time. Every tutorial I've seen using FormBuilder suggests subscribing to valueChanges of the input field, while piping debounceTime and distinctUntilChanged.

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

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

I cannot get this to work correctly. It appears to debounce the time properly, but when it gets piped through, it sends multiple of the final result (which distinctUntilChanged should handle). What am I doing wrong?

这是问题的快速视频(我添加了一个 tap 以便您可以看到网页记录了几个最终结果):

Here's a quick video of the problem (I added a tap so you can see that the webpage is logging several of the final result):

https://streamable.com/h2him

谢谢!

添加周围代码 source 函数也会在每次按键点击时运行,所以我认为我正在实例化多个 observable,而不管我的去抖.如何在其中添加去抖动逻辑?

Adding surrounding code the source function is run on each key click as well so I think that I'm instantiating multiple observables regardless of my debouncing. How can I add debounce logic within this?

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

推荐答案

我很确定这里的问题与 valueChanges 发出的对象有关.对于 distinctUntilChanged 发出的对象是不同的,您可能希望首先将此对象映射到您实际需要的值.(您也可以将回调传递给 distinctUntilChanged 来控制什么是区别)

i am pretty sure the issue here is related to the object that valueChanges emits. For the distinctUntilChanged the emitted object is different, you might want to map this object first to the value you actually need. (You can also hand a callback to distinctUntilChanged to control what is meant to be distinct)

例如

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

并且您肯定正在寻找 switchMap 而不是 mergeMap

and you are most certainly looking for switchMap over mergeMap

编辑

为了使用源函数,您可以像这样使用主题.

In order to work with the source function you can use a Subject like so.

var searchSubject = new Subject<any>();

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

比这个 searchSubject 你只在 ngOnInit 中订阅一次并在 onDestroy 函数中取消订阅.

than this searchSubject you subscribe only once in the ngOnInit and unsubscribe in onDestroy functions.

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

这篇关于使用 debounceTime &amp;订阅 FormBuilder valueChanges 时 distinctUntilChanged 不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆