首页 > 解决方案 > Angular typeahead debouncetime 请求

问题描述

搜索功能去抖动问题导致请求过多且debounceTime无法正常工作。

 <search"></search>
 search(argument: string): void {
    this.argument = argument;
      this.searchService
        .getSuggestions(this.argument )
        .pipe(debounceTime(8000), distinctUntilChanged(), take(1))
        .subscribe(
          (suggestions) => {
            this.suggestions= suggestions;
          }
        );
    }

标签: angularrxjstypeaheaddebounce

解决方案


您当前的实现不起作用的原因是您每次输入字符时都会创建一个新订阅。

 search(argument: string): void {
    // you don't need to do this
    this.argument = argument;
    // or this
    this.live = this.argument.length >= 3;
    if (this.live) {
      this.searchService
        .getSuggestions(this.argument )
        .pipe(debounceTime(8000), distinctUntilChanged(), take(1))
        // This subscription is then called every time you enter a value
        .subscribe(
          (suggestions: Array<string>) => {
            this.suggestions= suggestions;
            this.changeDetection.detectChanges();
          }
        );
    }

我会为您的搜索输入使用表单控件,如下所示:

<input [formControl]='myControl'>`

在您的 TS 中,将其声明为类变量:

myControl = new FormControl();

FormControl公开valueChanges为可观察的,然后您可以订阅。

然后你可能想做这样的事情:

suggestions$ = this.myControl.valueChanges.pipe(
    // use an RxJS filter here instead of using class variables like you were earlier
    filter(searchTerm => searchTerm?.length >= 3),
    distinctUntilChanged(),
    debounceTime(8000),
    // switchMap will subscribe to the inner observable 
    // and cancel any in flight XHR requests if you create a new one
    switchMap(valueChange => 
       this.searchService.getSuggestions(valueChange)
    )
)

我假设您将通过某种方式*ngFor迭代返回的建议,如下所示:

<suggestion 
    *ngFor="let suggestion of suggestions$ | async"
    [suggestion]="suggestion"
></suggestion>

使用async管道可确保您的订阅在组件销毁时得到整理。您可以通过其他方式执行此操作(您使用 的方法是正确的take(1)),但我的建议(双关语无意:D)是尽可能使用async管道。


推荐阅读