繁体   English   中英

Angular 9 - 在 typeahead 功能上避免多次 API 调用

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM