我有一个 html 搜索输入框,它连接到我的组件文件中的 ViewChild。
<input #userSearch type="text" placeholder="Search by Name or Email...">
@ViewChild('userSearch', {static: false}) set userSearch(input: ElementRef|null) {
if (!input) return;
this.setInput(input);
}
public setInput(input) {
fromEvent(input.nativeElement, 'keyup')
.pipe(
auditTime(1000),
map((event:any) => {
return event.target.value;
}),
debounceTime(1000),
distinctUntilChanged(),
)
.subscribe((text: string) => {
this.count++
console.log("count ++ is", this.count)
this.searchTerm = text;
console.log("this.searchTerm", this.searchTerm)
if (this.searchTerm.length > 2) {
this._loadUsers({
search_name_or_email: this.searchTerm
});
} else {
this._loadUsers();
}
});
}
在我的 setInput 函数中,我使用 debounceTime 和auditTime,目的是当用户完成输入时,该搜索词将被发送以进行 api 调用。
问题是,当我输入搜索词“Ron”时,我的 console.log 返回 count++ 为 1。当我删除我的搜索词时,该订阅会被触发多次,所以现在我的计数接近 8。当我输入新的搜索词时,计数会被触发到 15。每次我删除并添加新的搜索词时,订阅 block 被重复触发,这意味着 this._loadUsers 中的 api 调用被重复调用,这是一个问题。
我不明白为什么我的订阅 block 被调用了这么多次。我的理解是,使用 debounceTime 时,当用户完成输入时,在 debounceTime 解析后,就会触发订阅 block 。但由于某种原因,当用户完成输入时,订阅 block 会呈指数级触发?
更新:感谢您查看此内容。我删除了auditTime,但它仍然引起问题。我已将问题调试到构造函数中的此 setter 方法。我不熟悉这个 ViewChild setter 方法,但从一些文档中我发现 https://blog.angularindepth.com/beware-angular-can-steal-your-time-41fe589483df (第 #2 点),当 ref 输入元素嵌套在 *ngIf 内时必须使用。由于某种原因,这个 setter 方法在编辑搜索查询时会多次触发,我不确定为什么,因为我对 ViewChild 的 setter 方法不熟悉。
export class UsersComponent implements OnInit {
@ViewChild('userSearch', {static: false}) set userSearch(input: ElementRef|null) {
if (!input) return;
this.count++
console.log("count ++ is", this.count)
this.setInput(input);
}
最佳答案
使用主题而不是 fromEvent,如果您以这种方式销毁并重新创建搜索框,则只需创建一个可重用的可观察链,而不是每次都重新创建。按照您的方式,每次隐藏输入时,您都需要从旧链取消订阅。您有仍订阅该输入的孤立订阅。
<input type="text" placeholder="Search by Name or Email..." (keyup)="search($event.target.value)">
以及在 TypeScript 中
search$ = new Subject();
search(val) {
this.search$.next(val);
}
ngOnInit() {
this.search$
.pipe(
auditTime(1000),
map((event:any) => {
return event.target.value;
}),
debounceTime(1000),
distinctUntilChanged(),
)
.subscribe((text: string) => {
this.count++
console.log("count ++ is", this.count)
this.searchTerm = text;
console.log("this.searchTerm", this.searchTerm)
if (this.searchTerm.length > 2) {
this._loadUsers({
search_name_or_email: this.searchTerm
});
} else {
this._loadUsers();
}
});
}
关于javascript - 使用 RXJS 进行搜索输入,该输入进行 API 调用,但订阅会重复发生,即使使用 debounceTime,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58019099/