[英]Angular 9 - Avoiding multiple API calls on typeahead feature
我正在实现一个搜索框,它应该使用用户输入的值调用 API。 我想在用户停止输入几毫秒时拨打电话。
这适用于第一个请求:
this.searchForm.get('searchQuery').valueChanges.pipe(
filter(data => data.trim().length > 0),
debounceTime(500),
switchMap( (query: string) => this.productsService.searchProducts(query))
).subscribe();
但是,如果我继续输入,它会再等待 500 毫秒,然后发送多个请求(看起来等于输入的字符数)。
productsChanged = new Subject<Product[]>();
searchProducts(query: string) {
return this.http.get<Product[]>(this.baseUrl + '/products/search/' + query)
.pipe(
tap(products => {
this.products = products;
this.productsChanged.next(this.products.slice());
}));
}
这可能是非常简单的事情,但我似乎无法理解发生了什么。
Stackblitz: https://stackblitz.com/edit/angular-ivy-w4mbhm
解决方案
我发现了问题。
我在听(ngModelChange):
<input
name="searchQuery"
type="text"
[(ngModel)]="searchQuery"
(ngModelChange)="onSearch()"
formControlName="searchQuery" />
在那个监听器中,我将一个新的监听器附加到“valueChanges”。 因此,在每次击键时,都会创建一个新的侦听器。
正如预期的那样,一个简单的错误让我花了几个小时。
谢谢你的帮助!
就像我怀疑的那样,您不断地订阅您的表单更改。 您应该只在组件中执行一次(或者根本不执行,如果您使用async
管道):
ngOnInit(): void {
this.searchForm = new FormGroup({
searchQuery: new FormControl()
});
this.searchForm
.get("searchQuery")
.valueChanges.pipe(
filter(data => data?.trim().length > 0),
debounceTime(500),
switchMap((query: string) => this.productsService.searchProducts(query).pipe(
catchError((e) => of([])
)))
)
.subscribe((e) => {
console.log(e)
});
}
你也可以这样做:
ngOnInit(): void {
this.products$ = this.searchForm.get("searchQuery").valueChanges.pipe(
// ...
)
}
并使用异步 pipe。 这样您就不必在销毁时取消订阅
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.