在剑道字段更改中发出http请求+去抖动

时间:2017-02-15 12:43:15

标签: javascript angular rxjs kendo-ui-angular2

我有一个方法,每当某些输入文本发生变化时都会调用它。 (基本上是搜索) 我想延迟发布/获取请求,因此如果用户快速输入,则只会向服务器发送一个请求。

我在想这样的事情:

public partnerFilterChange(value)
{
    if (this.partnersSubscriptions)
        this.partnersSubscriptions.unsubscribe();

    this.partnersSubscriptions = this.partnersService.list({ filter: value })
        .debounceTime(5000)
        .subscribe(partners =>
        {
            delete this.partnersSubscriptions;
            this.partners = partners;
        });
}

但它不起作用。

立即执行Http请求,而不是在5秒后执行。我也尝试delay而不是debounceTime

编辑:

我正在使用kendo drop down list component and its change event,所以我无法控制函数调用,只能订阅http请求。

3 个答案:

答案 0 :(得分:2)

根据我的评论。由于您使用的是Kendo,因此无法直接使用form.get('fieldName').valueChanges。但是你可以将从Kendo收到的值推送到你自己的自定义observable,从而复制valueChanges的行为:

class AppComponent {
  // This is your own, custom observable that you'll subscribe to.
  // It will contain a stream of filter values received from Kendo.
  private _filterValues: Subject<string> = new Subject<string>();

  constructor() {
    // Start from your custom stream, debounce values, and run http query
    this._filterValues.asObservable()
      .debounceTime(400)
      .mergeMap(value => this.partnersService.list({ filter: value }))
      .subscribe(partners => this.partners = partners);
  }

  // This method is called by Kendo every time the field value changes.
  handleFilter(value) {
    // Push the value in the custom stream.
    this._filterValues.next(value);
  }
}

NB。此代码假定this.partnersService.list()返回一个observable。

使用此代码,每次更新字段时,都应刷新合作伙伴列表并应用去抖动。 (我还没有对代码进行测试,您可能需要根据自己的使用情况进行调整。)

答案 1 :(得分:0)

我的Angular 2应用程序中有类似的问题,我只想粘贴我的解决方案:

subscribeToSearchQueryChanges(){
        const sub = Observable.fromEvent(this.panelSuggestionBox.nativeElement, 'keyup')
            .debounceTime(300)
            .filter((kbE: KeyboardEvent) => {
                return !(kbE['code'] === 'Space' || kbE.key === 'ArrowDown' || kbE.key === 'ArrowUp' || kbE.key === 'Enter' || kbE.key === 'Tab' || kbE.key === 'Shift')
            })
            .map(() => _.trim(this.panelSuggestionBox.nativeElement.value) )
            .filter((term: string) => term.length > 2 )
            .switchMap((term: string) => this.suggestionService.getSuggestions(this.suggestionTypes, term))
            .subscribe((suggestions: Suggestion[]) => {
                this.suggestionsData = this.suggestionService.groupSuggestions(suggestions);
                this.toggleSuggestionList();
            }, err => {
                console.error('suggestions failed', err);
                this.removeSubscription(sub);
                this.subscribeToSearchQueryChanges();
            });

        this.addSubscription(sub);
    }

答案 2 :(得分:0)

import { Component, Output, HostListener, ChangeDetectionStrategy } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { FormGroup, FormControl } from '@angular/forms';

@Component({
  selector: 'my-user-search',
  changeDetection: ChangeDetectionStrategy.OnPush,
  template: `
    <form role="search" class="navbar-form-custom form-inline" [formGroup]="searchForm">
      <div class="form-group">
        <label for="user-search">Search</label>
        <input
          id="user-search"
          class="form-control"
          name="input"
          type="text"
          placeholder="Search Co-worker"
          formControlName="search"
        />
      </div>
    </form>
  `
})
export class UserSearchComponent {

  searchForm = new FormGroup({
    search: new FormControl('')
  });

  @Output() search: Observable<string> = this.searchForm.valueChanges
    .map(form => form.search)
    .debounceTime(700)
    .distinctUntilChanged();

  @HostListener('window:keyup', ['$event'])
  cancelSearch(event) {
    if (event.code === 'Escape') {
      this.searchForm.reset();
      // this.searchControl.setValue('', {emitEvent: true});
    }
  }

}

用法

$ event事件值是搜索词,并且当700ms过去且输入不同时,将首先调用(搜索)

<my-user-search (search)="handleSearch($event)"></my-user-search>