非常简单地说,我想在用户停止输入一段时间后执行查询。我看到的每个使用 FormBuilder
的教程都建议订阅输入字段的 valueChanges
,同时管道 debounceTime
和 distinctUntilChanged
.
this.threadForm.get('body').valueChanges.pipe(
debounceTime(500),
distinctUntilChanged(),
mergeMap(search => this.db.query$(...)`))
)
我无法让它正常工作。它似乎可以正确地对时间进行去抖动,但是当它通过管道传输时,它会发送多个最终结果(distinctUntilChanged 应该处理)。我做错了什么?
这是问题的快速视频(我添加了一个 tap
,所以您可以看到网页正在记录几个最终结果):
谢谢!
编辑:添加周围代码 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)
});
}
},
最佳答案
我很确定这里的问题与 valueChanges
发出的对象有关。对于 distinctUntilChanged
发出的对象是不同的,您可能希望首先将此对象映射到您实际需要的值。 (您也可以将回调传递给 distinctUntilChanged 以控制不同的内容)
例如
this.threadForm.get('body').valueChanges.pipe(
debounceTime(500),
map( (obj) => obj.searchVal ),
distinctUntilChanged(),
mergeMap(search => this.db.query$(...)`))
)
而且您肯定正在寻找 switchMap
而不是 mergeMap
编辑
为了使用 source 函数,您可以像这样使用 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$(...)`))
)
关于angular - 订阅 FormBuilder valueChanges 时,使用 debounceTime 和 distinctUntilChanged 不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55609210/