如何从字符串输入中使用 RxJs 5 的主题和去抖动

How to use subject and debounce with RxJs 5 from a string input

我不明白 Subject 对象如何为我试图在 Angular2 中实现的 Suggestion/Search 服务 工作。

假设每次输入更改时都会调用 generateSuggestions 以用于自动完成。

我不明白为什么我无法从 "next()" 调用中得到一些东西,typescript 编译器说它返回一个 void 类型。

我的目标是将每个更改提交到一个对象,该对象将决定每 500 毫秒在服务器上调用一个函数,而不是在每个键输入时发送垃圾邮件。

import { Jsonp, Response, Http } from 'angular2/http';
import * as Rx from 'rxjs/Rx';
import { Injectable } from 'angular2/core';

@Injectable()
export class SearchService {
    queryStream = new Rx.Subject();

    constructor(public http: Http) {

    }

    generateSuggestions(query: string) {
        this.queryStream
            .next(query)
            .debounce(500) // Compiler error: Debounce does not exist on type "void"
            .map(
                query => this.http.get('hellow')
                        .map( (res: Response) => res.json() )
                        .subscribe( results => console.log(results) )
            );
    }
}

我可以简单地做到这一点 JS/Typescript 但我真的很想尝试使用 RxJs,因为它已经被 Angular2 使用了。

这里犯了哪些错误?他们的官方网站上没有任何示例,文档真的很差。

注意:如果你有更好的选择,就post另一个答案,我会选择它作为答案。

我的结果表明我没有很好地理解 Rx.Subject 的目的。


使用 ngModel 和 ngModelChange 的建议解决方案

因为我目前只在我的组件中使用 ngModel,所以我不得不将 [(ngModel)] 拆分为 [ngModel] 和 (ngModelChange)

在组件构造函数中

使用 Rx.Subject(理论上它与 EventEmitter 相同,但也许它已经改变,因为我们无法再使用它访问所有 Rx.Subject 方法)参数化去抖并调用服务来检索值。

每次击键:

输入 -> (ngModelChange) -> eventEmitterComponentInstance.next(InputValue)

代码

SuggestMultipleStringComponent.ts

@Component({
  template: `<input [ngModel]="userInput"
                    (ngModelChange)="userInputChanged($event)" />`
  providers: [SearchService]
})
export class SuggestMultipleStringComponent { 
    private typeAheadEventEmitter = new Rx.Subject<string>();
    private userInput: string;
        
    constructor(private _searchService: SearchService) {
        this.typeAheadEventEmitter
                .pipe(
                   debounceTime(700),
                   switchMap(val => {
                      console.log('called once')
                      return this._searchService.callSomething();
                   })
                ).subscribe(results => {
                    console.log(results);
                }, error => {
                    console.log('error logged:');
                    console.log(error);
                });
      }

    userInputChanged(value: string) {
        this.userInput = value;
        this.typeAheadEventEmitter.next(value);
    }
}

SearchService.ts

@Injectable()
export class SearchService {
    
    constructor(private http: Http) {
        this.http = http;
    }
    
    callSomething() {
        return this.http.get('some/url')
                        .map((res: Response) => res.json());
    }
}