【问题标题】:Can't make debounceTime() or throttleTime() to work on an Angular http request无法使 debounceTime() 或 throttleTime() 处理 Angular http 请求
【发布时间】:2017-10-26 06:45:55
【问题描述】:

为了我的一生,我无法完成这项工作。 我搜索了再搜索,但找不到任何示例(所有示例都带有.fromEvent(),http.get 上没有)。

在我的模板中,我有这个输入:

<input type="text" (input)="categoriesSearch($event)">

在我的组件中,我有以下内容:

categoriesSearch(event) {
    this.categoriesSubscription = this.apiService
        .getCategoriesList(this.uploadForm.get('categories').value)
        .debounceTime(3000)
        // .throttleTime(3000)
        .subscribe(
            (response) => {
                this.categories = response.data;
            }
        );
}

这是我的 ApiService 中的方法:

getCategoriesList(keyword = null) {
    const headers = new Headers();
    headers.append('Content-Type', 'application/json');
    headers.append('Bearer', this.authService.user.token);

    const getParams: URLSearchParams = new URLSearchParams();
    getParams.set('keyword', keyword);
    return this.http.get(this.apiHost + '/categories', { headers: headers, search: getParams })
        .map(response => response.json());
}

在categoriesSearch()方法中,debounceTime()和throttleTime()都试过了(我也导入了,当然import 'rxjs/add/operator/debounceTime',import 'rxjs/add/operator/throttleTime')。

但是 http.get 请求根本没有去抖动或限制!如果我在 3 秒内输入 10 个字符,它会发出 10 个 http 请求。

我到底如何告诉this.http.get 仅在自上次请求或“无请求”(即最初的 3 秒延迟)以来至少 3 秒后才发出请求?好的,也许在这里我应该说“自从我上次在我的输入中输入了一些东西”。

我也尝试过直接在服务中使用 debounceTime()/throttleTime(),在 .map() 运算符之前 - 但结果是一样的。

【问题讨论】:

标签: angular rxjs5


【解决方案1】:

但是 http.get 请求根本没有去抖动或限制!如果我 在 3 秒内输入 10 个字符,它会发出 10 个 http 请求。

您以错误的方式实施。您需要先捕获输入,然后应用 denounce 并执行 HTTP 请求。

您可以通过多种方式实现

1) Observable.fromEvent

 <input type="text" #input>

组件

 @ViewChild('input') text: ElementRef;

  ngAfterViewInit() {
    let text$ = Observable.fromEvent(this.text.nativeElement, 'keyup')
     .do(() => console.log("keyup"))
    .debounceTime(3000)
     .distinctUntilChanged()
    .switchMap(() => getCategoriesList())
        .subscribe(res => console.log(res));
  }

2) 使用主题

<input type="text" (keyup)="search($event)">

组件

  searchTerms = new Subject<string>();

search(term: string): void {
    this.searchTerms.next(term);
  }

ngOnInit(): void {

    this.searchTerms
      .debounceTime(3000)
      .distinctUntilChanged()
      .switchMap(() => getCategoriesList())
      .subscribe(term => { 
       console.log();
     });

3) 使用表单控件

 <input type="text" [formControl]="term">

组件

  term = new FormControl();

  ngOnInit() {
    this.items = this.term.valueChanges
                 .debounceTime(3000)
                 .distinctUntilChanged()
                 .switchMap(term => getCategoriesList(term))
                 .subscribe(res => console.log(res));
  }

【讨论】:

  • 很抱歉这么晚才回来接受答案。谢谢!我原以为全能的 observable 会提供这样的东西......只需在 .subscribe() 之前添加 .debounceTime() 或 .throttleTime() 到任何 observable ,它就会自动知道如何处理它(跟踪时间和时刻它已被解雇等)。非常非常令人失望 :( 很遗憾,我不得不为了这个唯一目的制作另一个可观察的。RxJs 的耻辱!
  • 其实第二种方式行不通(看看github上有多少issues...)
  • 另一个使用 formControl 的工作示例:stackoverflow.com/questions/32051273/angular2-and-debounce
  • @MahmoudAliKassem 是的,当然。这个问题很老了,从 2017 年开始,在运营商可以管道之前 ?? (我假设你的意思是说 RxJs 6,而不是 JS6 ......我刚刚用谷歌搜索,发现可以管道的运营商是在 5.5 中引入的实际上)
  • @MrCroft 感谢您提供的信息,我将删除我的答案,但如果不使用管道,它对我不起作用,我认为这正是您提到的 RxJS
【解决方案2】:

执行下单操作很重要,把debounceTime移到getCategoriesList()上面就可以了

【讨论】:

    【解决方案3】:

    使用表单控件

     <input type="text" [formControl]="term">
    

    组件

    term = new FormControl();
    
      ngOnInit() {
        this.items = this.term.valueChanges
                     .debounceTime(3000)
                     .distinctUntilChanged()
                     .switchMap(term => getCategoriesList(term))
                     .subscribe(res => console.log(res));
      }
    

    【讨论】:

    • 似乎是已接受答案中 (3) 的复制和粘贴。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-10-28
    • 1970-01-01
    • 2021-05-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多