使用 debounceTime &订阅 FormBuilder valueChanges 时 distinctUntilChanged 不起作用 [英] Using debounceTime & distinctUntilChanged is not working when subscribing to FormBuilder valueChanges
问题描述
简单地说,我想在用户停止输入一段时间后执行查询.我见过的每个使用 FormBuilder
的教程都建议订阅输入字段的 valueChanges
,同时管道 debounceTime
和 distinctUntilChanged
.
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):
谢谢!
添加周围代码 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 &订阅 FormBuilder valueChanges 时 distinctUntilChanged 不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!