1

I am building an autocomplete function that is querying a backend for suggestions and would like to only get the last query that was made given a certain delay while the user is typing in an angular 5 form control. Currently my code looks like

 this.newVendorForm.get('address').valueChanges.pipe(delay(3000)).subscribe(
  address => {
    this.geocodeApi.getAddressSuggestions(address)
      .subscribe(
        response => {
          console.log('address suggestions');
          console.log(response);
          this.addressSuggestions = response;
        },
        error => {
          console.log('error getting address suggestion');
          console.log(error);
        }
      )
  }
);

This works however it makes a query for each typed in letter after 3000 ms. For example 'test' would query ['t', 'te', 'tes', 'test'] after 3000 ms. How can I just take the last change (i.e. 'test') from valueChanges after the 3000 ms delay and then do the subscribe? Thank you for you help

4

1 回答 1

4

你想要的是debounceTime和的混合switchMap

this.newVendorForm.get('address').valueChanges.pipe(
  debounceTime(3000),
  switchMap(address => this.geocodeApi.getAddressSuggestions(address).pipe(
    catchError(err => {
      console.error(err);
      return of();
    })
  )),
  filter(Boolean),
).subscribe(response => this.addressSuggestions = response);
  • debounceTime使得如果valueChanges在 3 秒内有两次发射,则只使用最后一个。这与delay将在更改完成 3 秒后发出所有更改不同。
  • switchMap接受一个内部的 observable,例如一个 http 请求,并将 observable 流更改为它——即您现在订阅了getAddressSuggestionsobservable 流。如果有东西发射到switchMap,它将取消之前的 observable。这样做的结果是,如果getAddressSuggestions在新的呼叫开始之前之前进行的呼叫尚未完成,则取消之前的呼叫。
  • ( catchErrorlettable operator version of .catch) 用于getAddressSuggestionsobservable 而不是 valueChanges。否则,如果 API 出现错误,则 valueChanges observable 将完成。使用catchErrorwhere 它允许您在不完成 valueChanges observable 的情况下处理错误。
  • filter用于仅发出具有值的响应。如果有错误,of()则不会发出。不过,这只是处理这种情况的一种方法。

最后,您可能希望避免使用手册.subscribe,因为您必须这样做.unsubscribe。相反,您可以尝试依赖| async模板中的管道来为您处理订阅。

于 2017-12-20T04:16:10.550 回答